From d98d80b07d826c69291fb0b553921f9c1b02759a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 13 May 2019 15:37:43 +0100 Subject: [PATCH 001/459] CPP: Improve locations for AV Rule 114.ql. --- cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql | 10 +++++++++- .../4.13 Functions/AV Rule 114/AV Rule 114.expected | 4 ++-- .../jsf/4.13 Functions/AV Rule 114/test.cpp | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql index ef5e224fe32..676b5a59093 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql @@ -30,7 +30,15 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) { ) and exists(ReturnStmt s | f.getAPredecessor() = s and - blame = s.getAPredecessor() + ( + ( + blame = s.getAPredecessor() and + count(blame.getASuccessor()) = 1 + ) or ( + blame = s and + exists(ControlFlowNode pred | pred = s.getAPredecessor() | count(pred.getASuccessor()) != 1) + ) + ) ) } diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected index 1644085ff12..ce056261514 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected @@ -4,9 +4,9 @@ | test.c:25:9:25:14 | ExprStmt | Function f4 should return a value of type int but does not return a value here | | test.c:39:9:39:14 | ExprStmt | Function f6 should return a value of type int but does not return a value here | | test.cpp:16:1:18:1 | { ... } | Function g2 should return a value of type MyValue but does not return a value here | -| test.cpp:48:2:48:26 | if (...) ... | Function g7 should return a value of type MyValue but does not return a value here | +| test.cpp:52:1:52:1 | return ... | Function g7 should return a value of type MyValue but does not return a value here | | test.cpp:74:1:76:1 | { ... } | Function g10 should return a value of type second but does not return a value here | | test.cpp:86:1:88:1 | { ... } | Function g12 should return a value of type second but does not return a value here | -| test.cpp:108:2:111:2 | if (...) ... | Function g14 should return a value of type int but does not return a value here | +| test.cpp:112:1:112:1 | return ... | Function g14 should return a value of type int but does not return a value here | | test.cpp:134:2:134:36 | ExprStmt | Function g16 should return a value of type int but does not return a value here | | test.cpp:141:3:141:37 | ExprStmt | Function g17 should return a value of type int but does not return a value here | diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp index 0dc0daf42c0..5421d7f9b05 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp @@ -48,7 +48,7 @@ MyValue g7(bool c) if (c) return MyValue(7); DONOTHING DONOTHING - // BAD [the alert here is unfortunately placed] + // GOOD } typedef void MYVOID; From 2fa846d1a6e71ab471a214bfaf1a01584e1f2d79 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 18 Jun 2019 15:41:17 +0100 Subject: [PATCH 002/459] CPP: Correct test. --- cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp index 5421d7f9b05..875c9ec4f75 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp @@ -48,7 +48,7 @@ MyValue g7(bool c) if (c) return MyValue(7); DONOTHING DONOTHING - // GOOD + // BAD } typedef void MYVOID; From e8139c0f31dd44eacec77f7961dbf7a76899147f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Oct 2019 17:24:42 +0100 Subject: [PATCH 003/459] CPP: Autoformat. --- cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql index 676b5a59093..713f92b39ef 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql @@ -31,13 +31,11 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) { exists(ReturnStmt s | f.getAPredecessor() = s and ( - ( - blame = s.getAPredecessor() and - count(blame.getASuccessor()) = 1 - ) or ( - blame = s and - exists(ControlFlowNode pred | pred = s.getAPredecessor() | count(pred.getASuccessor()) != 1) - ) + blame = s.getAPredecessor() and + count(blame.getASuccessor()) = 1 + or + blame = s and + exists(ControlFlowNode pred | pred = s.getAPredecessor() | count(pred.getASuccessor()) != 1) ) ) } From 170981ef418ebc7d353d7ef3401796fd67d7edbe Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 14 Jan 2020 14:36:44 +0000 Subject: [PATCH 004/459] CPP: Change note. --- change-notes/1.24/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.24/analysis-cpp.md b/change-notes/1.24/analysis-cpp.md index 53ab2a9e1cb..1cb048e6c4f 100644 --- a/change-notes/1.24/analysis-cpp.md +++ b/change-notes/1.24/analysis-cpp.md @@ -18,6 +18,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. | Memory is never freed (`cpp/memory-never-freed`) | More true positive results | This query now identifies a wider variety of buffer allocations using the `semmle.code.cpp.models.interfaces.Allocation` library. | | Memory may not be freed (`cpp/memory-may-not-be-freed`) | More true positive results | This query now identifies a wider variety of buffer allocations using the `semmle.code.cpp.models.interfaces.Allocation` library. | | Missing return statement (`cpp/missing-return`) | Fewer false positive results | Functions containing `asm` statements are no longer highlighted by this query. | +| Missing return statement (`cpp/missing-return`) | More accurate locations | Locations reported by this query are now more accurate in some cases. | | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. | | No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. | | Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. | From 1a458aa4501d4ce2895a53044e36e3b036293478 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 18 Nov 2019 15:00:33 -0800 Subject: [PATCH 005/459] C++: IR dataflow edges through outparams --- .../ir/dataflow/internal/DataFlowPrivate.qll | 75 +++++++++++++++++-- .../aliased_ssa/Instruction.qll | 9 +-- .../cpp/ir/implementation/raw/Instruction.qll | 9 +-- .../raw/internal/TranslatedFunction.qll | 5 ++ .../unaliased_ssa/Instruction.qll | 9 +-- .../ir/implementation/raw/Instruction.qll | 9 +-- .../unaliased_ssa/Instruction.qll | 9 +-- 7 files changed, 88 insertions(+), 37 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index c5e84383215..0644e963f8e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -24,7 +24,9 @@ class ArgumentNode extends Node { DataFlowCall getCall() { this.argumentOf(result, _) } } -private newtype TReturnKind = TNormalReturnKind() +private newtype TReturnKind = + TNormalReturnKind() or + TIndirectReturnKind(ParameterIndex index) /** * A return kind. A return kind describes how a value can be returned @@ -32,32 +34,91 @@ private newtype TReturnKind = TNormalReturnKind() */ class ReturnKind extends TReturnKind { /** Gets a textual representation of this return kind. */ - string toString() { result = "return" } + abstract string toString(); +} + +private class NormalReturnKind extends ReturnKind, TNormalReturnKind { + override string toString() { result = "return" } +} + +private class IndirectReturnKind extends ReturnKind, TIndirectReturnKind { + ParameterIndex index; + + IndirectReturnKind() { + this = TIndirectReturnKind(index) + } + + override string toString() { result = "outparam[" + index.toString() +"]" } } /** A data flow node that occurs as the result of a `ReturnStmt`. */ class ReturnNode extends Node { - ReturnNode() { exists(ReturnValueInstruction ret | this.asInstruction() = ret.getReturnValue()) } + Instruction primary; + ReturnNode() { + exists(ReturnValueInstruction ret | this.asInstruction() = ret.getReturnValue() and primary = ret) + or + exists(ReturnIndirectionInstruction rii | this.asInstruction() = rii.getSideEffectOperand().getAnyDef() and primary = rii) + } /** Gets the kind of this returned value. */ - ReturnKind getKind() { result = TNormalReturnKind() } + abstract ReturnKind getKind(); +} + +class ReturnValueNode extends ReturnNode { + override ReturnValueInstruction primary; + + override ReturnKind getKind() { result = TNormalReturnKind() } +} + +class ReturnIndirectionNode extends ReturnNode { + override ReturnIndirectionInstruction primary; + + override ReturnKind getKind() { result = TIndirectReturnKind(primary.getParameter().getIndex()) } } /** A data flow node that represents the output of a call. */ class OutNode extends Node { - override CallInstruction instr; + OutNode() { + instr instanceof CallInstruction or + instr instanceof WriteSideEffectInstruction + } /** Gets the underlying call. */ - DataFlowCall getCall() { result = instr } + abstract DataFlowCall getCall(); + + abstract ReturnKind getReturnKind(); } +private class CallOutNode extends OutNode { + override CallInstruction instr; + + override DataFlowCall getCall() { + result = instr + } + + override ReturnKind getReturnKind() { + result instanceof NormalReturnKind + } +} + +private class SideEffectOutNode extends OutNode { + override WriteSideEffectInstruction instr; + + override DataFlowCall getCall() { + result = instr.getPrimaryInstruction() + } + + override ReturnKind getReturnKind() { + result = TIndirectReturnKind(instr.getIndex()) + } +} /** * Gets a node that can read the value returned from `call` with return kind * `kind`. */ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { result.getCall() = call and - kind = TNormalReturnKind() + result.getReturnKind() = kind } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 7514f580813..eb404c40638 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -743,7 +743,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -753,6 +753,8 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { @@ -1237,11 +1239,6 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } -} - -/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 7514f580813..eb404c40638 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -743,7 +743,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -753,6 +753,8 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { @@ -1237,11 +1239,6 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } -} - -/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 88e5c6bef9f..3fabebd2001 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -628,4 +628,9 @@ class TranslatedReadEffect extends TranslatedElement, TTranslatedReadEffect { operandTag = sideEffectOperand() and result = getUnknownType() } + + final override IRVariable getInstructionVariable(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = getIRUserVariable(getFunction(), param) + } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 7514f580813..eb404c40638 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -743,7 +743,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -753,6 +753,8 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { @@ -1237,11 +1239,6 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } -} - -/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 7514f580813..eb404c40638 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -743,7 +743,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -753,6 +753,8 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { @@ -1237,11 +1239,6 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } -} - -/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 7514f580813..eb404c40638 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -743,7 +743,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -753,6 +753,8 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { @@ -1237,11 +1239,6 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { - BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } -} - -/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { From 74ea9bcdf4f40112304fda4f9b241b2923d057c4 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 29 Jan 2020 12:23:11 -0800 Subject: [PATCH 006/459] C++: fix merge issue --- .../code/cpp/ir/implementation/aliased_ssa/Instruction.qll | 5 +++++ .../semmle/code/cpp/ir/implementation/raw/Instruction.qll | 5 +++++ .../code/cpp/ir/implementation/unaliased_ssa/Instruction.qll | 5 +++++ .../semmle/code/csharp/ir/implementation/raw/Instruction.qll | 5 +++++ .../csharp/ir/implementation/unaliased_ssa/Instruction.qll | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index eb404c40638..d7a99025cc9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -1239,6 +1239,11 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { + BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } +} + +/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index eb404c40638..d7a99025cc9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -1239,6 +1239,11 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { + BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } +} + +/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index eb404c40638..d7a99025cc9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1239,6 +1239,11 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { + BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } +} + +/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index eb404c40638..d7a99025cc9 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -1239,6 +1239,11 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { + BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } +} + +/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index eb404c40638..d7a99025cc9 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1239,6 +1239,11 @@ class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { /** * An instruction representing the read of an indirect buffer parameter within a function call. */ +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { + BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } +} + +/** * An instruction representing the read of an indirect buffer parameter within a function call. */ class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { From 71d87be773655e7245d1c9d26d6a69ca4deb3747 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 29 Jan 2020 17:51:42 -0800 Subject: [PATCH 007/459] C++: add flow through partial loads in DTT --- .../code/cpp/ir/dataflow/DefaultTaintTracking.qll | 10 ++++++++++ .../DefaultTaintTracking/defaulttainttracking.cpp | 10 ++++++++++ .../dataflow/DefaultTaintTracking/tainted.expected | 7 +++++++ .../dataflow/DefaultTaintTracking/test_diff.expected | 7 +++++++ .../library-tests/dataflow/dataflow-tests/test.cpp | 10 ++++++++++ 5 files changed, 44 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index f6ad5246d8e..38b02b47d7c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -147,6 +147,8 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Flow through pointer dereference i2.(LoadInstruction).getSourceAddress() = i1 or + i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 + or i2.(UnaryInstruction).getUnary() = i1 or i2.(ChiInstruction).getPartial() = i1 and @@ -311,6 +313,14 @@ predicate tainted(Expr source, Element tainted) { ) } +predicate tainted_instruction(Function sourceFunc,Instruction source, Function sinkFunc, Instruction sink) { + sourceFunc = source.getEnclosingFunction() and + sinkFunc = sink.getEnclosingFunction() and + exists(DefaultTaintTrackingCfg cfg | + cfg.hasFlow(DataFlow::instructionNode(source), DataFlow::instructionNode(sink)) + ) +} + predicate taintedIncludingGlobalVars(Expr source, Element tainted, string globalVar) { tainted(source, tainted) and globalVar = "" diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp index ebe38f1f060..b73dd0ab4f7 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp @@ -77,4 +77,14 @@ void test_dynamic_cast() { reinterpret_cast(b2)->f(getenv("VAR")); dynamic_cast(b2)->f(getenv("VAR")); // tainted [FALSE POSITIVE] +} + +void flow_to_outparam(char ** ret, char *arg) { + *ret = arg; +} + +void test_outparams() { + char *p2 = nullptr; + flow_to_outparam(&p2, getenv("VAR")); + sink(p2); // tainted } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected index 92948eeffc6..14fe03c3472 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected @@ -89,6 +89,13 @@ | defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:79:30:79:35 | call to getenv | | defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:79:30:79:42 | (const char *)... | | defaulttainttracking.cpp:79:30:79:35 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:82:42:82:44 | arg | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:83:12:83:14 | arg | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:88:27:88:32 | call to getenv | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:89:10:89:11 | (const char *)... | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:89:10:89:11 | p2 | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | | test_diff.cpp:92:10:92:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 | | test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:1:11:1:20 | p#0 | | test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:13 | argv | diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected index c557f43f1c7..5c1c27541c6 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected @@ -9,6 +9,13 @@ | defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:36:39:61 | (const char *)... | AST only | | defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:51:39:61 | env_pointer | AST only | | defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p | IR only | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | IR only | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:82:31:82:33 | ret | AST only | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:83:5:83:8 | * ... | AST only | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:83:6:83:8 | ret | AST only | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:89:10:89:11 | (const char *)... | IR only | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | defaulttainttracking.cpp:89:10:89:11 | p2 | IR only | +| defaulttainttracking.cpp:88:27:88:32 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | IR only | | test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only | | test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:36:24:36:24 | p | AST only | | test_diff.cpp:111:10:111:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index 6c445fb76c1..666edf7a177 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -460,3 +460,13 @@ void throughStmtExpr(int source1, int clean1) { }); sink(local); // tainted } + +void intOutparamSource(int *p) { + *p = source(); +} + +void viaOutparam() { + int x = 0; + intOutparamSource(&x); + sink(x); // tainted [FALSE NEGATIVE] +} \ No newline at end of file From 8d37c0320924163c6f331106517ea31e2b28fa38 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 4 Feb 2020 16:26:09 +0100 Subject: [PATCH 008/459] using pseudo-properties to model URL parsing --- .../javascript/dataflow/TaintTracking.qll | 88 ++++++++++++++----- .../query-tests/Security/CWE-079/Xss.expected | 9 ++ .../test/query-tests/Security/CWE-079/tst.js | 11 +++ 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index be1df8bc7c2..e99713de31e 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -602,45 +602,89 @@ module TaintTracking { } /** - * Holds if `params` is a `URLSearchParams` object providing access to - * the parameters encoded in `input`. + * Holds if `params` is a construction of a `URLSearchParams` that parses + * the parameters in `input`. */ - predicate isUrlSearchParams(DataFlow::SourceNode params, DataFlow::Node input) { + private predicate isUrlSearchParams(DataFlow::SourceNode params, DataFlow::Node input) { exists(DataFlow::GlobalVarRefNode urlSearchParams, NewExpr newUrlSearchParams | urlSearchParams.getName() = "URLSearchParams" and newUrlSearchParams = urlSearchParams.getAnInstantiation().asExpr() and params.asExpr() = newUrlSearchParams and input.asExpr() = newUrlSearchParams.getArgument(0) ) - or - exists(DataFlow::NewNode newUrl | - newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and - params = newUrl.getAPropertyRead("searchParams") and - input = newUrl.getArgument(0) - ) + } + + /** + * A pseudo-property used to store a value on a `URLSearchParams` that + * can be obtained with a `get` or `getAll` call. + */ + private string hiddenUrlPseudoProperty() { + result = "$hiddenSearchPararms" } /** * A taint propagating data flow edge arising from URL parameter parsing. */ - private class UrlSearchParamsTaintStep extends AdditionalTaintStep, DataFlow::ValueNode { - DataFlow::Node source; - + private class UrlSearchParamsTaintStep extends DataFlow::AdditionalFlowStep { UrlSearchParamsTaintStep() { - // either this is itself an `URLSearchParams` object - isUrlSearchParams(this, source) + this = DataFlow::globalVarRef("URL") or + this = DataFlow::globalVarRef("URLSearchParams") + } + + /** + * Holds if `succ` is a `URLSearchParams` providing access to the + * parameters encoded in `pred`. + */ + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + isUrlSearchParams(succ, pred) + } + + /** + * Holds if `pred` should be stored in the object `succ` under the property `prop`. + * + * This step is used to model 2 facts: + * 1) A `URL` constructed using `url = new URL(input)` transfers taint from `input` to `url.searchParams`. + * 2) A `URLSearchParams` (either `url.searchParams` or `new URLSearchParams(input)`) has a tainted value, + * which is stored in a pseudo-property, that can later be access using a `get` or `getAll` call. + */ + override predicate storeStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + (prop = "searchParams" or prop = hiddenUrlPseudoProperty()) and + exists(DataFlow::NewNode newUrl | succ = newUrl | + newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and + pred = newUrl.getArgument(0) + ) or - // or this is a call to `get` or `getAll` on a `URLSearchParams` object - exists(DataFlow::SourceNode searchParams, string m | - isUrlSearchParams(searchParams, source) and - this = searchParams.getAMethodCall(m) and - m.matches("get%") + prop = hiddenUrlPseudoProperty() and + isUrlSearchParams(succ, pred) + } + + /** + * Holds if the property `prop` should be copied from the object `pred` to the object `succ`. + * + * This step is used to copy a value the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. + */ + override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + prop = hiddenUrlPseudoProperty() and + exists(DataFlow::PropRead write | write = succ | + write.getPropertyName() = "searchParams" and + write.getBase() = pred ) } - override predicate step(DataFlow::Node pred, DataFlow::Node succ) { - pred = source and succ = this - } + /** + * Holds if the property `prop` of the object `pred` should be loaded into `succ`. + * + * This step is used to load the value stored in the hidden pseudo-property. + */ + override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + prop = hiddenUrlPseudoProperty() and + // this is a call to `get` or `getAll` on a `URLSearchParams` object + exists(string m, DataFlow::MethodCallNode call | call = succ | + call.getMethodName() = m and + call.getReceiver() = pred and + m.matches("get%") + ) + } } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected index 60d36dfb765..5f8bf041b2b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected @@ -333,6 +333,10 @@ nodes | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | +| tst.js:330:18:330:34 | document.location | +| tst.js:336:18:336:35 | params.get('name') | +| tst.js:336:18:336:35 | params.get('name') | | typeahead.js:20:13:20:45 | target | | typeahead.js:20:22:20:38 | document.location | | typeahead.js:20:22:20:38 | document.location | @@ -642,6 +646,10 @@ edges | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | | typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target | | typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search | | typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search | @@ -741,6 +749,7 @@ edges | tst.js:306:20:306:20 | e | tst.js:304:9:304:16 | location | tst.js:306:20:306:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:304:9:304:16 | location | user-provided value | | tst.js:314:20:314:20 | e | tst.js:311:10:311:17 | location | tst.js:314:20:314:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:311:10:311:17 | location | user-provided value | | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | Cross-site scripting vulnerability due to $@. | tst.js:319:35:319:42 | location | user-provided value | +| tst.js:336:18:336:35 | params.get('name') | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | Cross-site scripting vulnerability due to $@. | tst.js:330:18:330:34 | document.location | user-provided value | | typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:38 | document.location | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:38 | document.location | user-provided value | | v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value | | winjs.js:3:43:3:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:3:43:3:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/tst.js b/javascript/ql/test/query-tests/Security/CWE-079/tst.js index 1ec5610ff83..cb30969fd58 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/tst.js @@ -324,4 +324,15 @@ function test2() { // OK $('myId').html(target.length) +} + +function getTaintedUrl() { + return new URL(document.location); +} + +function URLPseudoProperties() { + // NOT OK + let params = getTaintedUrl().searchParams; + $('name').html(params.get('name')); + } \ No newline at end of file From e525cf095917e9c8323ad9e5ad6896a6046ba128 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 09:40:16 +0100 Subject: [PATCH 009/459] generalize `isAdditionalLoadStoreStep` such that it loads and stores different properties --- .../javascript/dataflow/Configuration.qll | 51 +++++++++++++++---- .../CustomLoadStoreSteps/test.expected | 1 + .../CustomLoadStoreSteps/test.ql | 8 +++ .../library-tests/CustomLoadStoreSteps/tst.js | 12 ++++- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index f281a8aa23e..3f1c3c364d4 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -246,6 +246,15 @@ abstract class Configuration extends string { predicate isAdditionalLoadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. + */ + predicate isAdditionalLoadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + none() + } } /** @@ -515,6 +524,17 @@ abstract class AdditionalFlowStep extends DataFlow::Node { */ cached predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. + */ + cached + predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + loadProp = storeProp and + loadStoreStep(pred, succ, loadProp) + } } /** @@ -619,7 +639,7 @@ private predicate exploratoryFlowStep( basicLoadStep(pred, succ, _) or isAdditionalStoreStep(pred, succ, _, cfg) or isAdditionalLoadStep(pred, succ, _, cfg) or - isAdditionalLoadStoreStep(pred, succ, _, cfg) or + isAdditionalLoadStoreStep(pred, succ, _, _, cfg) or // the following two disjuncts taken together over-approximate flow through // higher-order calls callback(pred, succ) or @@ -859,14 +879,21 @@ private predicate isAdditionalStoreStep( } /** - * Holds if the property `prop` should be copied from the object `pred` to the object `succ`. + * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. */ private predicate isAdditionalLoadStoreStep( - DataFlow::Node pred, DataFlow::Node succ, string prop, DataFlow::Configuration cfg + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp, DataFlow::Configuration cfg ) { - any(AdditionalFlowStep s).loadStoreStep(pred, succ, prop) + any(AdditionalFlowStep s).loadStoreStep(pred, succ, loadProp, storeProp) or - cfg.isAdditionalLoadStoreStep(pred, succ, prop) + cfg.isAdditionalLoadStoreStep(pred, succ, loadProp, storeProp) + or + loadProp = storeProp and + ( + any(AdditionalFlowStep s).loadStoreStep(pred, succ, loadProp) + or + cfg.isAdditionalLoadStoreStep(pred, succ, loadProp) + ) } /** @@ -904,12 +931,14 @@ private predicate reachableFromStoreBase( or exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary | reachableFromStoreBase(prop, rhs, mid, cfg, oldSummary) and - ( - flowStep(mid, cfg, nd, newSummary) - or - isAdditionalLoadStoreStep(mid, nd, prop, cfg) and - newSummary = PathSummary::level() - ) and + flowStep(mid, cfg, nd, newSummary) and + summary = oldSummary.appendValuePreserving(newSummary) + ) + or + exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary, string midProp | + reachableFromStoreBase(midProp, rhs, mid, cfg, oldSummary) and + isAdditionalLoadStoreStep(mid, nd, midProp, prop, cfg) and + newSummary = PathSummary::level() and summary = oldSummary.appendValuePreserving(newSummary) ) } diff --git a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected index b53738c569a..acfd9f12beb 100644 --- a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected +++ b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected @@ -1 +1,2 @@ | tst.js:4:15:4:22 | "source" | tst.js:9:7:9:24 | readTaint(tainted) | +| tst.js:4:15:4:22 | "source" | tst.js:15:7:15:20 | tainted3.other | diff --git a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql index e4ffc89294d..f9622784925 100644 --- a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql +++ b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql @@ -19,6 +19,14 @@ class Configuration extends TaintTracking::Configuration { ) and prop = "bar" } + + // calling .copy("foo", "bar") actually moves a property from "foo" to "bar". + override predicate isAdditionalLoadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + exists(DataFlow::MethodCallNode call | call.getMethodName() = "copy" and call = succ and pred = call.getReceiver() | + call.getArgument(0).mayHaveStringValue(loadProp) and + call.getArgument(1).mayHaveStringValue(storeProp) + ) + } } from DataFlow::Node pred, DataFlow::Node succ, Configuration cfg diff --git a/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js b/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js index c3fff1b4187..95806a2122d 100644 --- a/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js +++ b/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js @@ -6,5 +6,15 @@ function readTaint(x) { return x.foo; } - sink(readTaint(tainted)); + sink(readTaint(tainted)); // NOT OK + + + var tainted2 = {myProp: source}; + + var tainted3 = tainted2.copy("myProp", "other"); + sink(tainted3.other); // NOT OK. + + var tainted4 = tainted2.copy("other", "myProp"); // does nothing, there is no "other" on tainted2. + sink(tainted4.other); // OK. + })(); \ No newline at end of file From 76aca02752ec98aa88563b36c50a151c4625b706 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 10:27:03 +0100 Subject: [PATCH 010/459] change the pseudo-property on URL to a two-stage process --- javascript/ql/src/Security/CWE-079/Xss.actual | 3 +++ .../javascript/dataflow/TaintTracking.qll | 23 +++++++++++++------ .../test/query-tests/Security/CWE-079/tst.js | 4 ++++ 3 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 javascript/ql/src/Security/CWE-079/Xss.actual diff --git a/javascript/ql/src/Security/CWE-079/Xss.actual b/javascript/ql/src/Security/CWE-079/Xss.actual new file mode 100644 index 00000000000..ac992895b9c --- /dev/null +++ b/javascript/ql/src/Security/CWE-079/Xss.actual @@ -0,0 +1,3 @@ +nodes +edges +#select diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index e99713de31e..593586e2821 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -615,13 +615,21 @@ module TaintTracking { } /** - * A pseudo-property used to store a value on a `URLSearchParams` that - * can be obtained with a `get` or `getAll` call. + * A pseudo-property a `URL` that stores a value that can be obtained + * with a `get` or `getAll` call to the `searchParams` property. */ private string hiddenUrlPseudoProperty() { result = "$hiddenSearchPararms" } + /** + * A pseudo-property on a `URLSearchParams` that can be obtained + * with a `get` or `getAll` call. + */ + private string getableUrlPseudoProperty() { + result = "$gettableSearchPararms" + } + /** * A taint propagating data flow edge arising from URL parameter parsing. */ @@ -654,17 +662,18 @@ module TaintTracking { pred = newUrl.getArgument(0) ) or - prop = hiddenUrlPseudoProperty() and + prop = getableUrlPseudoProperty() and isUrlSearchParams(succ, pred) } /** - * Holds if the property `prop` should be copied from the object `pred` to the object `succ`. + * Holds if the property `loadStep` should be copied from the object `pred` to the property `storeStep` of object `succ`. * * This step is used to copy a value the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. */ - override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { - prop = hiddenUrlPseudoProperty() and + override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + loadProp = hiddenUrlPseudoProperty() and + storeProp = getableUrlPseudoProperty() and exists(DataFlow::PropRead write | write = succ | write.getPropertyName() = "searchParams" and write.getBase() = pred @@ -677,7 +686,7 @@ module TaintTracking { * This step is used to load the value stored in the hidden pseudo-property. */ override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { - prop = hiddenUrlPseudoProperty() and + prop = getableUrlPseudoProperty() and // this is a call to `get` or `getAll` on a `URLSearchParams` object exists(string m, DataFlow::MethodCallNode call | call = succ | call.getMethodName() = m and diff --git a/javascript/ql/test/query-tests/Security/CWE-079/tst.js b/javascript/ql/test/query-tests/Security/CWE-079/tst.js index cb30969fd58..a5fefc233eb 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/tst.js @@ -335,4 +335,8 @@ function URLPseudoProperties() { let params = getTaintedUrl().searchParams; $('name').html(params.get('name')); + // OK (.get is not defined on a URL) + let myUrl = getTaintedUrl(); + $('name').html(myUrl.get('name')); + } \ No newline at end of file From 35a7e15a2f4e6ed9bce8a97f22cbc2ba59d2c5a8 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 10:30:31 +0100 Subject: [PATCH 011/459] remove `private` modifer on `isUrlSearchParams` --- javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 593586e2821..0c5cbe3a76c 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -605,7 +605,7 @@ module TaintTracking { * Holds if `params` is a construction of a `URLSearchParams` that parses * the parameters in `input`. */ - private predicate isUrlSearchParams(DataFlow::SourceNode params, DataFlow::Node input) { + predicate isUrlSearchParams(DataFlow::SourceNode params, DataFlow::Node input) { exists(DataFlow::GlobalVarRefNode urlSearchParams, NewExpr newUrlSearchParams | urlSearchParams.getName() = "URLSearchParams" and newUrlSearchParams = urlSearchParams.getAnInstantiation().asExpr() and From ec9c37075cef441155745b83ed784503018b1c50 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 10:31:53 +0100 Subject: [PATCH 012/459] address review feedback --- .../ql/src/semmle/javascript/dataflow/TaintTracking.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 0c5cbe3a76c..ae015bd0d33 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -669,14 +669,14 @@ module TaintTracking { /** * Holds if the property `loadStep` should be copied from the object `pred` to the property `storeStep` of object `succ`. * - * This step is used to copy a value the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. + * This step is used to copy the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. */ override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { loadProp = hiddenUrlPseudoProperty() and storeProp = getableUrlPseudoProperty() and - exists(DataFlow::PropRead write | write = succ | - write.getPropertyName() = "searchParams" and - write.getBase() = pred + exists(DataFlow::PropRead read | read = succ | + read.getPropertyName() = "searchParams" and + read.getBase() = pred ) } From ffc6fdddddcbffe7b87947f47274b001901887ab Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 10:52:40 +0100 Subject: [PATCH 013/459] update expected test output --- .../Security/CWE-079/XssWithAdditionalSources.expected | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected index 8581759032e..c7fdb071a2b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected @@ -333,6 +333,10 @@ nodes | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | +| tst.js:330:18:330:34 | document.location | +| tst.js:336:18:336:35 | params.get('name') | +| tst.js:336:18:336:35 | params.get('name') | | typeahead.js:9:28:9:30 | loc | | typeahead.js:9:28:9:30 | loc | | typeahead.js:10:16:10:18 | loc | @@ -646,6 +650,10 @@ edges | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | From 30d5eb5a13aa74a12434ecd71c7b965bbc63a8fd Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 10:53:34 +0100 Subject: [PATCH 014/459] update docstrings --- .../src/semmle/javascript/dataflow/TaintTracking.qll | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index ae015bd0d33..fdcf03358d4 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -650,10 +650,11 @@ module TaintTracking { /** * Holds if `pred` should be stored in the object `succ` under the property `prop`. * - * This step is used to model 2 facts: - * 1) A `URL` constructed using `url = new URL(input)` transfers taint from `input` to `url.searchParams`. - * 2) A `URLSearchParams` (either `url.searchParams` or `new URLSearchParams(input)`) has a tainted value, - * which is stored in a pseudo-property, that can later be access using a `get` or `getAll` call. + * This step is used to model 3 facts: + * 1) A `URL` constructed using `url = new URL(input)` transfers taint from `input` to `url.searchParams`. (See prop = "searchParams") + * 2) Accessing the `searchParams` on a `URL` results in a `URLSearchParams` object (See the loadStoreStep method on this class and hiddenUrlPseudoProperty()) + * 3) A `URLSearchParams` object (either `url.searchParams` or `new URLSearchParams(input)`) has a tainted value, + * which can be accessed using a `get` or `getAll` call. (See getableUrlPseudoProperty()) */ override predicate storeStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { (prop = "searchParams" or prop = hiddenUrlPseudoProperty()) and @@ -670,6 +671,7 @@ module TaintTracking { * Holds if the property `loadStep` should be copied from the object `pred` to the property `storeStep` of object `succ`. * * This step is used to copy the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. + * For an expression `url.searchParams`, the property `hiddenUrlPseudoProperty()` from the `url` object is stored in the property `getableUrlPseudoProperty()` on `url.searchParams`. */ override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { loadProp = hiddenUrlPseudoProperty() and @@ -683,7 +685,7 @@ module TaintTracking { /** * Holds if the property `prop` of the object `pred` should be loaded into `succ`. * - * This step is used to load the value stored in the hidden pseudo-property. + * This step is used to load the value stored in the pseudo-property `getableUrlPseudoProperty()`. */ override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { prop = getableUrlPseudoProperty() and From 88bb1dc23dd92e58119c7b1927f306a5fc0cab7d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 10:58:13 +0100 Subject: [PATCH 015/459] bind `this` in each of the step methods of `UrlSearchParamsTaintStep` --- .../javascript/dataflow/TaintTracking.qll | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index fdcf03358d4..bf7068adb67 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -633,18 +633,13 @@ module TaintTracking { /** * A taint propagating data flow edge arising from URL parameter parsing. */ - private class UrlSearchParamsTaintStep extends DataFlow::AdditionalFlowStep { - UrlSearchParamsTaintStep() { - this = DataFlow::globalVarRef("URL") or - this = DataFlow::globalVarRef("URLSearchParams") - } - + private class UrlSearchParamsTaintStep extends DataFlow::AdditionalFlowStep, DataFlow::ValueNode { /** * Holds if `succ` is a `URLSearchParams` providing access to the * parameters encoded in `pred`. */ override predicate step(DataFlow::Node pred, DataFlow::Node succ) { - isUrlSearchParams(succ, pred) + isUrlSearchParams(succ, pred) and succ = this } /** @@ -657,14 +652,16 @@ module TaintTracking { * which can be accessed using a `get` or `getAll` call. (See getableUrlPseudoProperty()) */ override predicate storeStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { - (prop = "searchParams" or prop = hiddenUrlPseudoProperty()) and - exists(DataFlow::NewNode newUrl | succ = newUrl | - newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and - pred = newUrl.getArgument(0) + succ = this and ( + (prop = "searchParams" or prop = hiddenUrlPseudoProperty()) and + exists(DataFlow::NewNode newUrl | succ = newUrl | + newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and + pred = newUrl.getArgument(0) + ) + or + prop = getableUrlPseudoProperty() and + isUrlSearchParams(succ, pred) ) - or - prop = getableUrlPseudoProperty() and - isUrlSearchParams(succ, pred) } /** @@ -674,6 +671,7 @@ module TaintTracking { * For an expression `url.searchParams`, the property `hiddenUrlPseudoProperty()` from the `url` object is stored in the property `getableUrlPseudoProperty()` on `url.searchParams`. */ override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + succ = this and loadProp = hiddenUrlPseudoProperty() and storeProp = getableUrlPseudoProperty() and exists(DataFlow::PropRead read | read = succ | @@ -688,6 +686,7 @@ module TaintTracking { * This step is used to load the value stored in the pseudo-property `getableUrlPseudoProperty()`. */ override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + succ = this and prop = getableUrlPseudoProperty() and // this is a call to `get` or `getAll` on a `URLSearchParams` object exists(string m, DataFlow::MethodCallNode call | call = succ | From da28d3b9716b23e2dcb8e23c9d44938454c4abfe Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 5 Feb 2020 12:44:10 +0100 Subject: [PATCH 016/459] add "hash" and "search" to URL taint step --- .../ql/src/semmle/javascript/dataflow/TaintTracking.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index bf7068adb67..92c5321d368 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -646,14 +646,14 @@ module TaintTracking { * Holds if `pred` should be stored in the object `succ` under the property `prop`. * * This step is used to model 3 facts: - * 1) A `URL` constructed using `url = new URL(input)` transfers taint from `input` to `url.searchParams`. (See prop = "searchParams") + * 1) A `URL` constructed using `url = new URL(input)` transfers taint from `input` to `url.searchParams`, `url.hash`, and `url.search`. * 2) Accessing the `searchParams` on a `URL` results in a `URLSearchParams` object (See the loadStoreStep method on this class and hiddenUrlPseudoProperty()) * 3) A `URLSearchParams` object (either `url.searchParams` or `new URLSearchParams(input)`) has a tainted value, * which can be accessed using a `get` or `getAll` call. (See getableUrlPseudoProperty()) */ override predicate storeStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { succ = this and ( - (prop = "searchParams" or prop = hiddenUrlPseudoProperty()) and + (prop = "searchParams" or prop = "hash" or prop = "search" or prop = hiddenUrlPseudoProperty()) and exists(DataFlow::NewNode newUrl | succ = newUrl | newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and pred = newUrl.getArgument(0) From 2d3a742b7f0e9cf49502cb31820bfbbc419f04e7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 6 Feb 2020 13:41:00 -0800 Subject: [PATCH 017/459] C++: autoformat and accept test changes --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 4 +- .../ir/dataflow/internal/DataFlowPrivate.qll | 38 +++++------- .../ir/ir/aliased_ssa_sanity.expected | 3 + .../test/library-tests/ir/ir/raw_ir.expected | 62 +++++++++---------- .../ir/ssa/aliased_ssa_ir.expected | 30 ++++----- .../ir/ssa/aliased_ssa_ir_unsound.expected | 30 ++++----- .../ir/ssa/unaliased_ssa_ir.expected | 30 ++++----- .../ir/ssa/unaliased_ssa_ir_unsound.expected | 30 ++++----- 8 files changed, 114 insertions(+), 113 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 4cf09b6e481..a4148865036 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -348,7 +348,9 @@ predicate tainted(Expr source, Element tainted) { ) } -predicate tainted_instruction(Function sourceFunc,Instruction source, Function sinkFunc, Instruction sink) { +predicate tainted_instruction( + Function sourceFunc, Instruction source, Function sinkFunc, Instruction sink +) { sourceFunc = source.getEnclosingFunction() and sinkFunc = sink.getEnclosingFunction() and exists(DefaultTaintTrackingCfg cfg | diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 0644e963f8e..f1e4598220b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -24,7 +24,7 @@ class ArgumentNode extends Node { DataFlowCall getCall() { this.argumentOf(result, _) } } -private newtype TReturnKind = +private newtype TReturnKind = TNormalReturnKind() or TIndirectReturnKind(ParameterIndex index) @@ -44,20 +44,23 @@ private class NormalReturnKind extends ReturnKind, TNormalReturnKind { private class IndirectReturnKind extends ReturnKind, TIndirectReturnKind { ParameterIndex index; - IndirectReturnKind() { - this = TIndirectReturnKind(index) - } + IndirectReturnKind() { this = TIndirectReturnKind(index) } - override string toString() { result = "outparam[" + index.toString() +"]" } + override string toString() { result = "outparam[" + index.toString() + "]" } } /** A data flow node that occurs as the result of a `ReturnStmt`. */ class ReturnNode extends Node { Instruction primary; + ReturnNode() { - exists(ReturnValueInstruction ret | this.asInstruction() = ret.getReturnValue() and primary = ret) + exists(ReturnValueInstruction ret | + this.asInstruction() = ret.getReturnValue() and primary = ret + ) or - exists(ReturnIndirectionInstruction rii | this.asInstruction() = rii.getSideEffectOperand().getAnyDef() and primary = rii) + exists(ReturnIndirectionInstruction rii | + this.asInstruction() = rii.getSideEffectOperand().getAnyDef() and primary = rii + ) } /** Gets the kind of this returned value. */ @@ -67,13 +70,13 @@ class ReturnNode extends Node { class ReturnValueNode extends ReturnNode { override ReturnValueInstruction primary; - override ReturnKind getKind() { result = TNormalReturnKind() } + override ReturnKind getKind() { result = TNormalReturnKind() } } class ReturnIndirectionNode extends ReturnNode { override ReturnIndirectionInstruction primary; - override ReturnKind getKind() { result = TIndirectReturnKind(primary.getParameter().getIndex()) } + override ReturnKind getKind() { result = TIndirectReturnKind(primary.getParameter().getIndex()) } } /** A data flow node that represents the output of a call. */ @@ -92,26 +95,19 @@ class OutNode extends Node { private class CallOutNode extends OutNode { override CallInstruction instr; - override DataFlowCall getCall() { - result = instr - } + override DataFlowCall getCall() { result = instr } - override ReturnKind getReturnKind() { - result instanceof NormalReturnKind - } + override ReturnKind getReturnKind() { result instanceof NormalReturnKind } } private class SideEffectOutNode extends OutNode { override WriteSideEffectInstruction instr; - override DataFlowCall getCall() { - result = instr.getPrimaryInstruction() - } + override DataFlowCall getCall() { result = instr.getPrimaryInstruction() } - override ReturnKind getReturnKind() { - result = TIndirectReturnKind(instr.getIndex()) - } + override ReturnKind getReturnKind() { result = TIndirectReturnKind(instr.getIndex()) } } + /** * Gets a node that can read the value returned from `call` with return kind * `kind`. diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index e5e666c020b..852f84b84b9 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -1,8 +1,11 @@ missingOperand +| ir.cpp:736:5:736:19 | Chi: call to String | Instruction 'Chi' is missing an expected operand with tag 'ChiTotal' in function '$@'. | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | | ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:1145:5:1145:19 | Chi: call to String | Instruction 'Chi' is missing an expected operand with tag 'ChiTotal' in function '$@'. | ir.cpp:1133:6:1133:23 | IR: TryCatchNoCatchAny | void TryCatchNoCatchAny(bool) | +| ir.cpp:1170:3:1170:33 | Chi: call to String | Instruction 'Chi' is missing an expected operand with tag 'ChiTotal' in function '$@'. | ir.cpp:1169:8:1169:30 | IR: ReturnConstructorResult | String ReturnConstructorResult() | unexpectedOperand duplicateOperand missingPhiOperand diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 6420d52ee6d..b291aaebd1a 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -79,7 +79,7 @@ bad_asts.cpp: # 27| r27_6(Point) = Load : &:r27_5, ~mu26_4 # 27| mu27_7(Point) = Store : &:r27_1, r27_6 # 28| v28_1(void) = NoOp : -# 26| v26_9(void) = ReturnIndirection : &:r26_7, ~mu26_4 +# 26| v26_9(void) = ReturnIndirection[a] : &:r26_7, ~mu26_4 # 26| v26_10(void) = ReturnVoid : # 26| v26_11(void) = UnmodeledUse : mu* # 26| v26_12(void) = AliasedUse : ~mu26_4 @@ -836,7 +836,7 @@ ir.cpp: # 168| r168_6(glval) = VariableAddress[b] : # 168| mu168_7(bool) = Store : &:r168_6, r168_5 # 169| v169_1(void) = NoOp : -# 153| v153_11(void) = ReturnIndirection : &:r153_7, ~mu153_4 +# 153| v153_11(void) = ReturnIndirection[p] : &:r153_7, ~mu153_4 # 153| v153_12(void) = ReturnVoid : # 153| v153_13(void) = UnmodeledUse : mu* # 153| v153_14(void) = AliasedUse : ~mu153_4 @@ -923,7 +923,7 @@ ir.cpp: # 184| r184_7(glval) = PointerAdd[4] : r184_4, r184_6 # 184| mu184_8(int) = Store : &:r184_7, r184_2 # 185| v185_1(void) = NoOp : -# 171| v171_11(void) = ReturnIndirection : &:r171_7, ~mu171_4 +# 171| v171_11(void) = ReturnIndirection[p] : &:r171_7, ~mu171_4 # 171| v171_12(void) = ReturnVoid : # 171| v171_13(void) = UnmodeledUse : mu* # 171| v171_14(void) = AliasedUse : ~mu171_4 @@ -1023,8 +1023,8 @@ ir.cpp: # 201| r201_6(glval) = VariableAddress[b] : # 201| mu201_7(bool) = Store : &:r201_6, r201_5 # 202| v202_1(void) = NoOp : -# 193| v193_13(void) = ReturnIndirection : &:r193_7, ~mu193_4 -# 193| v193_14(void) = ReturnIndirection : &:r193_11, ~mu193_4 +# 193| v193_13(void) = ReturnIndirection[p] : &:r193_7, ~mu193_4 +# 193| v193_14(void) = ReturnIndirection[q] : &:r193_11, ~mu193_4 # 193| v193_15(void) = ReturnVoid : # 193| v193_16(void) = UnmodeledUse : mu* # 193| v193_17(void) = AliasedUse : ~mu193_4 @@ -1073,7 +1073,7 @@ ir.cpp: # 210| r210_7(glval) = VariableAddress[q] : # 210| mu210_8(int *) = Store : &:r210_7, r210_6 # 211| v211_1(void) = NoOp : -# 204| v204_9(void) = ReturnIndirection : &:r204_7, ~mu204_4 +# 204| v204_9(void) = ReturnIndirection[p] : &:r204_7, ~mu204_4 # 204| v204_10(void) = ReturnVoid : # 204| v204_11(void) = UnmodeledUse : mu* # 204| v204_12(void) = AliasedUse : ~mu204_4 @@ -1684,7 +1684,7 @@ ir.cpp: # 343| r343_3(int *) = Load : &:r343_2, ~mu341_4 # 343| r343_4(int) = Load : &:r343_3, ~mu341_4 # 343| mu343_5(int) = Store : &:r343_1, r343_4 -# 341| v341_9(void) = ReturnIndirection : &:r341_7, ~mu341_4 +# 341| v341_9(void) = ReturnIndirection[p] : &:r341_7, ~mu341_4 # 341| r341_10(glval) = VariableAddress[#return] : # 341| v341_11(void) = ReturnValue : &:r341_10, ~mu341_4 # 341| v341_12(void) = UnmodeledUse : mu* @@ -2984,8 +2984,8 @@ ir.cpp: # 625| v625_6(void) = ^BufferReadSideEffect[-1] : &:r625_2, ~mu622_4 # 625| mu625_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r625_2 # 626| v626_1(void) = NoOp : -# 622| v622_15(void) = ReturnIndirection : &:r622_7, ~mu622_4 -# 622| v622_16(void) = ReturnIndirection : &:r622_11, ~mu622_4 +# 622| v622_15(void) = ReturnIndirection[r] : &:r622_7, ~mu622_4 +# 622| v622_16(void) = ReturnIndirection[p] : &:r622_11, ~mu622_4 # 622| v622_17(void) = ReturnVoid : # 622| v622_18(void) = UnmodeledUse : mu* # 622| v622_19(void) = AliasedUse : ~mu622_4 @@ -3177,7 +3177,7 @@ ir.cpp: # 676| r676_3(int &) = Load : &:r676_2, ~mu675_4 # 676| r676_4(int) = Load : &:r676_3, ~mu675_4 # 676| mu676_5(int) = Store : &:r676_1, r676_4 -# 675| v675_9(void) = ReturnIndirection : &:r675_7, ~mu675_4 +# 675| v675_9(void) = ReturnIndirection[r] : &:r675_7, ~mu675_4 # 675| r675_10(glval) = VariableAddress[#return] : # 675| v675_11(void) = ReturnValue : &:r675_10, ~mu675_4 # 675| v675_12(void) = UnmodeledUse : mu* @@ -3370,7 +3370,7 @@ ir.cpp: # 716| r716_1(glval) = VariableAddress[#return] : # 716| r716_2(long) = Constant[0] : # 716| mu716_3(long) = Store : &:r716_1, r716_2 -# 715| v715_11(void) = ReturnIndirection : &:r715_7, ~mu715_4 +# 715| v715_11(void) = ReturnIndirection[x] : &:r715_7, ~mu715_4 # 715| r715_12(glval) = VariableAddress[#return] : # 715| v715_13(void) = ReturnValue : &:r715_12, ~mu715_4 # 715| v715_14(void) = UnmodeledUse : mu* @@ -3557,7 +3557,7 @@ ir.cpp: #-----| r0_20(glval) = CopyValue : r0_19 #-----| r0_21(Base &) = CopyValue : r0_20 #-----| mu0_22(Base &) = Store : &:r0_18, r0_21 -#-----| v0_23(void) = ReturnIndirection : &:r0_3, ~mu745_4 +#-----| v0_23(void) = ReturnIndirection[p#0] : &:r0_3, ~mu745_4 # 745| r745_9(glval) = VariableAddress[#return] : # 745| v745_10(void) = ReturnValue : &:r745_9, ~mu745_4 # 745| v745_11(void) = UnmodeledUse : mu* @@ -3581,7 +3581,7 @@ ir.cpp: # 745| mu745_9(unknown) = ^CallSideEffect : ~mu745_4 # 745| mu745_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r745_6 # 745| v745_11(void) = NoOp : -#-----| v0_5(void) = ReturnIndirection : &:r0_3, ~mu745_4 +#-----| v0_5(void) = ReturnIndirection[p#0] : &:r0_3, ~mu745_4 # 745| v745_12(void) = ReturnVoid : # 745| v745_13(void) = UnmodeledUse : mu* # 745| v745_14(void) = AliasedUse : ~mu745_4 @@ -3671,7 +3671,7 @@ ir.cpp: #-----| r0_34(glval) = CopyValue : r0_33 #-----| r0_35(Middle &) = CopyValue : r0_34 #-----| mu0_36(Middle &) = Store : &:r0_32, r0_35 -#-----| v0_37(void) = ReturnIndirection : &:r0_3, ~mu754_4 +#-----| v0_37(void) = ReturnIndirection[p#0] : &:r0_3, ~mu754_4 # 754| r754_12(glval) = VariableAddress[#return] : # 754| v754_13(void) = ReturnValue : &:r754_12, ~mu754_4 # 754| v754_14(void) = UnmodeledUse : mu* @@ -3771,7 +3771,7 @@ ir.cpp: #-----| r0_34(glval) = CopyValue : r0_33 #-----| r0_35(Derived &) = CopyValue : r0_34 #-----| mu0_36(Derived &) = Store : &:r0_32, r0_35 -#-----| v0_37(void) = ReturnIndirection : &:r0_3, ~mu763_4 +#-----| v0_37(void) = ReturnIndirection[p#0] : &:r0_3, ~mu763_4 # 763| r763_12(glval) = VariableAddress[#return] : # 763| v763_13(void) = ReturnValue : &:r763_12, ~mu763_4 # 763| v763_14(void) = UnmodeledUse : mu* @@ -4328,10 +4328,10 @@ ir.cpp: #-----| mu0_4(PolymorphicBase) = ^IndirectMayWriteSideEffect[-1] : &:r850_1 # 851| r851_1(glval) = VariableAddress[d] : # 851| mu851_2(PolymorphicDerived) = Uninitialized[d] : &:r851_1 -#-----| r0_5(glval) = FunctionAddress[PolymorphicDerived] : -#-----| v0_6(void) = Call : func:r0_5, this:r851_1 -#-----| mu0_7(unknown) = ^CallSideEffect : ~mu849_4 -#-----| mu0_8(PolymorphicDerived) = ^IndirectMayWriteSideEffect[-1] : &:r851_1 +# 851| r851_3(glval) = FunctionAddress[PolymorphicDerived] : +# 851| v851_4(void) = Call : func:r851_3, this:r851_1 +# 851| mu851_5(unknown) = ^CallSideEffect : ~mu849_4 +# 851| mu851_6(PolymorphicDerived) = ^IndirectMayWriteSideEffect[-1] : &:r851_1 # 853| r853_1(glval) = VariableAddress[pb] : # 853| r853_2(glval) = VariableAddress[b] : # 853| r853_3(PolymorphicBase *) = CopyValue : r853_2 @@ -4475,7 +4475,7 @@ ir.cpp: # 885| r885_4(glval<..(*)(..)>) = VariableAddress[pfn] : # 885| mu885_5(..(*)(..)) = Store : &:r885_4, r885_3 # 886| v886_1(void) = NoOp : -# 883| v883_11(void) = ReturnIndirection : &:r883_9, ~mu883_4 +# 883| v883_11(void) = ReturnIndirection[p] : &:r883_9, ~mu883_4 # 883| v883_12(void) = ReturnVoid : # 883| v883_13(void) = UnmodeledUse : mu* # 883| v883_14(void) = AliasedUse : ~mu883_4 @@ -4959,7 +4959,7 @@ ir.cpp: # 988| mu988_11(unknown) = ^CallSideEffect : ~mu987_4 # 988| r988_12(int) = Add : r988_6, r988_10 # 988| mu988_13(int) = Store : &:r988_1, r988_12 -# 987| v987_11(void) = ReturnIndirection : &:r987_7, ~mu987_4 +# 987| v987_11(void) = ReturnIndirection[a] : &:r987_7, ~mu987_4 # 987| r987_12(glval) = VariableAddress[#return] : # 987| v987_13(void) = ReturnValue : &:r987_12, ~mu987_4 # 987| v987_14(void) = UnmodeledUse : mu* @@ -5269,7 +5269,7 @@ ir.cpp: # 1046| v1046_7(void) = ^BufferReadSideEffect[-1] : &:r1046_2, ~mu1031_4 # 1046| mu1046_8(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r1046_2 # 1047| v1047_1(void) = NoOp : -# 1031| v1031_11(void) = ReturnIndirection : &:r1031_9, ~mu1031_4 +# 1031| v1031_11(void) = ReturnIndirection[s] : &:r1031_9, ~mu1031_4 # 1031| v1031_12(void) = ReturnVoid : # 1031| v1031_13(void) = UnmodeledUse : mu* # 1031| v1031_14(void) = AliasedUse : ~mu1031_4 @@ -5620,13 +5620,13 @@ ir.cpp: #-----| Goto -> Block 5 # 1079| Block 5 -# 1079| v1079_1(void) = NoOp : -# 1080| v1080_1(void) = NoOp : -# 1068| v1068_9(void) = ReturnIndirection : &:r1068_7, ~mu1068_4 -# 1068| v1068_10(void) = ReturnVoid : -# 1068| v1068_11(void) = UnmodeledUse : mu* -# 1068| v1068_12(void) = AliasedUse : ~mu1068_4 -# 1068| v1068_13(void) = ExitFunction : +# 1079| v1079_1(void) = NoOp : +# 1080| v1080_1(void) = NoOp : +# 1068| v1068_9(void) = ReturnIndirection[v] : &:r1068_7, ~mu1068_4 +# 1068| v1068_10(void) = ReturnVoid : +# 1068| v1068_11(void) = UnmodeledUse : mu* +# 1068| v1068_12(void) = AliasedUse : ~mu1068_4 +# 1068| v1068_13(void) = ExitFunction : #-----| Block 6 #-----| r0_24(glval) = VariableAddress[(__begin)] : @@ -5753,8 +5753,8 @@ ir.cpp: # 1109| r1109_9(unsigned int) = Load : &:r1109_8, ~mu1104_4 # 1106| mu1106_1(unknown) = InlineAsm : ~mu1104_4, 0:r1109_3, 1:r1109_4, 2:r1109_7, 3:r1109_9 # 1111| v1111_1(void) = NoOp : -# 1104| v1104_17(void) = ReturnIndirection : &:r1104_7, ~mu1104_4 -# 1104| v1104_18(void) = ReturnIndirection : &:r1104_13, ~mu1104_4 +# 1104| v1104_17(void) = ReturnIndirection[a] : &:r1104_7, ~mu1104_4 +# 1104| v1104_18(void) = ReturnIndirection[c] : &:r1104_13, ~mu1104_4 # 1104| v1104_19(void) = ReturnVoid : # 1104| v1104_20(void) = UnmodeledUse : mu* # 1104| v1104_21(void) = AliasedUse : ~mu1104_4 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 5c12a3d2173..32caabbe079 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -89,7 +89,7 @@ ssa.cpp: # 28| r28_12(int) = Load : &:r28_11, m28_1 # 28| r28_13(int) = Add : r28_8, r28_12 # 28| m28_14(int) = Store : &:r28_4, r28_13 -# 13| v13_14(void) = ReturnIndirection : &:r13_8, m28_3 +# 13| v13_14(void) = ReturnIndirection[p] : &:r13_8, m28_3 # 13| r13_15(glval) = VariableAddress[#return] : # 13| v13_16(void) = ReturnValue : &:r13_15, m28_14 # 13| v13_17(void) = UnmodeledUse : mu* @@ -257,12 +257,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_12(void) = ReturnIndirection : &:r68_10, m68_11 -# 68| v68_13(void) = ReturnVoid : -# 68| v68_14(void) = UnmodeledUse : mu* -# 68| v68_15(void) = AliasedUse : ~m69_3 -# 68| v68_16(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_12(void) = ReturnIndirection[p] : &:r68_10, m68_11 +# 68| v68_13(void) = ReturnVoid : +# 68| v68_14(void) = UnmodeledUse : mu* +# 68| v68_15(void) = AliasedUse : ~m69_3 +# 68| v68_16(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -806,7 +806,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_7 # 181| r181_4(int) = Load : &:r181_3, ~m179_9 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_10(void) = ReturnIndirection : &:r179_8, m179_9 +# 179| v179_10(void) = ReturnIndirection[p] : &:r179_8, m179_9 # 179| r179_11(glval) = VariableAddress[#return] : # 179| v179_12(void) = ReturnValue : &:r179_11, m181_5 # 179| v179_13(void) = UnmodeledUse : mu* @@ -851,10 +851,10 @@ ssa.cpp: # 186| m186_1(unknown) = InlineAsm : ~m184_13, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 186| m186_2(unknown) = Chi : total:m184_13, partial:m186_1 # 192| v192_1(void) = NoOp : -# 184| v184_22(void) = ReturnIndirection : &:r184_8, ~m186_2 -# 184| v184_23(void) = ReturnIndirection : &:r184_12, ~m186_2 -# 184| v184_24(void) = ReturnIndirection : &:r184_16, m184_17 -# 184| v184_25(void) = ReturnIndirection : &:r184_20, m184_21 +# 184| v184_22(void) = ReturnIndirection[a] : &:r184_8, ~m186_2 +# 184| v184_23(void) = ReturnIndirection[b] : &:r184_12, ~m186_2 +# 184| v184_24(void) = ReturnIndirection[c] : &:r184_16, m184_17 +# 184| v184_25(void) = ReturnIndirection[d] : &:r184_20, m184_21 # 184| v184_26(void) = ReturnVoid : # 184| v184_27(void) = UnmodeledUse : mu* # 184| v184_28(void) = AliasedUse : ~m186_2 @@ -913,8 +913,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_16(void) = ReturnIndirection : &:r198_8, m198_9 -# 198| v198_17(void) = ReturnIndirection : &:r198_12, m198_13 +# 198| v198_16(void) = ReturnIndirection[str1] : &:r198_8, m198_9 +# 198| v198_17(void) = ReturnIndirection[str2] : &:r198_12, m198_13 # 198| r198_18(glval) = VariableAddress[#return] : # 198| v198_19(void) = ReturnValue : &:r198_18, m202_4 # 198| v198_20(void) = UnmodeledUse : mu* @@ -1186,7 +1186,7 @@ ssa.cpp: # 251| r251_2(glval) = VariableAddress[dst] : # 251| r251_3(char *) = Load : &:r251_2, m248_12 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_12(void) = ReturnIndirection : &:r247_8, ~m250_13 +# 247| v247_12(void) = ReturnIndirection[src] : &:r247_8, ~m250_13 # 247| r247_13(glval) = VariableAddress[#return] : # 247| v247_14(void) = ReturnValue : &:r247_13, m251_4 # 247| v247_15(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index 2a012447a68..1d3ad55c2ef 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -89,7 +89,7 @@ ssa.cpp: # 28| r28_12(int) = Load : &:r28_11, m28_1 # 28| r28_13(int) = Add : r28_8, r28_12 # 28| m28_14(int) = Store : &:r28_4, r28_13 -# 13| v13_14(void) = ReturnIndirection : &:r13_8, m28_3 +# 13| v13_14(void) = ReturnIndirection[p] : &:r13_8, m28_3 # 13| r13_15(glval) = VariableAddress[#return] : # 13| v13_16(void) = ReturnValue : &:r13_15, m28_14 # 13| v13_17(void) = UnmodeledUse : mu* @@ -257,12 +257,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_12(void) = ReturnIndirection : &:r68_10, m68_11 -# 68| v68_13(void) = ReturnVoid : -# 68| v68_14(void) = UnmodeledUse : mu* -# 68| v68_15(void) = AliasedUse : ~m69_3 -# 68| v68_16(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_12(void) = ReturnIndirection[p] : &:r68_10, m68_11 +# 68| v68_13(void) = ReturnVoid : +# 68| v68_14(void) = UnmodeledUse : mu* +# 68| v68_15(void) = AliasedUse : ~m69_3 +# 68| v68_16(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -803,7 +803,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_7 # 181| r181_4(int) = Load : &:r181_3, ~m179_9 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_10(void) = ReturnIndirection : &:r179_8, m179_9 +# 179| v179_10(void) = ReturnIndirection[p] : &:r179_8, m179_9 # 179| r179_11(glval) = VariableAddress[#return] : # 179| v179_12(void) = ReturnValue : &:r179_11, m181_5 # 179| v179_13(void) = UnmodeledUse : mu* @@ -848,10 +848,10 @@ ssa.cpp: # 186| m186_1(unknown) = InlineAsm : ~m184_4, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 186| m186_2(unknown) = Chi : total:m184_4, partial:m186_1 # 192| v192_1(void) = NoOp : -# 184| v184_22(void) = ReturnIndirection : &:r184_8, m184_9 -# 184| v184_23(void) = ReturnIndirection : &:r184_12, m184_13 -# 184| v184_24(void) = ReturnIndirection : &:r184_16, m184_17 -# 184| v184_25(void) = ReturnIndirection : &:r184_20, m184_21 +# 184| v184_22(void) = ReturnIndirection[a] : &:r184_8, m184_9 +# 184| v184_23(void) = ReturnIndirection[b] : &:r184_12, m184_13 +# 184| v184_24(void) = ReturnIndirection[c] : &:r184_16, m184_17 +# 184| v184_25(void) = ReturnIndirection[d] : &:r184_20, m184_21 # 184| v184_26(void) = ReturnVoid : # 184| v184_27(void) = UnmodeledUse : mu* # 184| v184_28(void) = AliasedUse : ~m186_2 @@ -910,8 +910,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_16(void) = ReturnIndirection : &:r198_8, m198_9 -# 198| v198_17(void) = ReturnIndirection : &:r198_12, m198_13 +# 198| v198_16(void) = ReturnIndirection[str1] : &:r198_8, m198_9 +# 198| v198_17(void) = ReturnIndirection[str2] : &:r198_12, m198_13 # 198| r198_18(glval) = VariableAddress[#return] : # 198| v198_19(void) = ReturnValue : &:r198_18, m202_4 # 198| v198_20(void) = UnmodeledUse : mu* @@ -1181,7 +1181,7 @@ ssa.cpp: # 251| r251_2(glval) = VariableAddress[dst] : # 251| r251_3(char *) = Load : &:r251_2, m248_12 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_12(void) = ReturnIndirection : &:r247_8, ~m249_6 +# 247| v247_12(void) = ReturnIndirection[src] : &:r247_8, ~m249_6 # 247| r247_13(glval) = VariableAddress[#return] : # 247| v247_14(void) = ReturnValue : &:r247_13, m251_4 # 247| v247_15(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 4319cb86587..90d5c8690a6 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -78,7 +78,7 @@ ssa.cpp: # 28| r28_9(int) = Load : &:r28_8, ~mu13_4 # 28| r28_10(int) = Add : r28_5, r28_9 # 28| m28_11(int) = Store : &:r28_1, r28_10 -# 13| v13_13(void) = ReturnIndirection : &:r13_7, ~mu13_4 +# 13| v13_13(void) = ReturnIndirection[p] : &:r13_7, ~mu13_4 # 13| r13_14(glval) = VariableAddress[#return] : # 13| v13_15(void) = ReturnValue : &:r13_14, m28_11 # 13| v13_16(void) = UnmodeledUse : mu* @@ -249,12 +249,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_11(void) = ReturnIndirection : &:r68_9, ~mu68_4 -# 68| v68_12(void) = ReturnVoid : -# 68| v68_13(void) = UnmodeledUse : mu* -# 68| v68_14(void) = AliasedUse : ~mu68_4 -# 68| v68_15(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, ~mu68_4 +# 68| v68_12(void) = ReturnVoid : +# 68| v68_13(void) = UnmodeledUse : mu* +# 68| v68_14(void) = AliasedUse : ~mu68_4 +# 68| v68_15(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -752,7 +752,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_6 # 181| r181_4(int) = Load : &:r181_3, ~mu179_4 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_9(void) = ReturnIndirection : &:r179_7, ~mu179_4 +# 179| v179_9(void) = ReturnIndirection[p] : &:r179_7, ~mu179_4 # 179| r179_10(glval) = VariableAddress[#return] : # 179| v179_11(void) = ReturnValue : &:r179_10, m181_5 # 179| v179_12(void) = UnmodeledUse : mu* @@ -795,10 +795,10 @@ ssa.cpp: # 190| r190_6(unsigned int) = Load : &:r190_5, ~mu184_4 # 186| mu186_1(unknown) = InlineAsm : ~mu184_4, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 192| v192_1(void) = NoOp : -# 184| v184_21(void) = ReturnIndirection : &:r184_7, ~mu184_4 -# 184| v184_22(void) = ReturnIndirection : &:r184_11, ~mu184_4 -# 184| v184_23(void) = ReturnIndirection : &:r184_15, ~mu184_4 -# 184| v184_24(void) = ReturnIndirection : &:r184_19, ~mu184_4 +# 184| v184_21(void) = ReturnIndirection[a] : &:r184_7, ~mu184_4 +# 184| v184_22(void) = ReturnIndirection[b] : &:r184_11, ~mu184_4 +# 184| v184_23(void) = ReturnIndirection[c] : &:r184_15, ~mu184_4 +# 184| v184_24(void) = ReturnIndirection[d] : &:r184_19, ~mu184_4 # 184| v184_25(void) = ReturnVoid : # 184| v184_26(void) = UnmodeledUse : mu* # 184| v184_27(void) = AliasedUse : ~mu184_4 @@ -856,8 +856,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_15(void) = ReturnIndirection : &:r198_7, ~mu198_4 -# 198| v198_16(void) = ReturnIndirection : &:r198_11, ~mu198_4 +# 198| v198_15(void) = ReturnIndirection[str1] : &:r198_7, ~mu198_4 +# 198| v198_16(void) = ReturnIndirection[str2] : &:r198_11, ~mu198_4 # 198| r198_17(glval) = VariableAddress[#return] : # 198| v198_18(void) = ReturnValue : &:r198_17, m202_4 # 198| v198_19(void) = UnmodeledUse : mu* @@ -1099,7 +1099,7 @@ ssa.cpp: # 251| r251_2(glval) = VariableAddress[dst] : # 251| r251_3(char *) = Load : &:r251_2, m248_11 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_11(void) = ReturnIndirection : &:r247_7, ~mu247_4 +# 247| v247_11(void) = ReturnIndirection[src] : &:r247_7, ~mu247_4 # 247| r247_12(glval) = VariableAddress[#return] : # 247| v247_13(void) = ReturnValue : &:r247_12, m251_4 # 247| v247_14(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index 4319cb86587..90d5c8690a6 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -78,7 +78,7 @@ ssa.cpp: # 28| r28_9(int) = Load : &:r28_8, ~mu13_4 # 28| r28_10(int) = Add : r28_5, r28_9 # 28| m28_11(int) = Store : &:r28_1, r28_10 -# 13| v13_13(void) = ReturnIndirection : &:r13_7, ~mu13_4 +# 13| v13_13(void) = ReturnIndirection[p] : &:r13_7, ~mu13_4 # 13| r13_14(glval) = VariableAddress[#return] : # 13| v13_15(void) = ReturnValue : &:r13_14, m28_11 # 13| v13_16(void) = UnmodeledUse : mu* @@ -249,12 +249,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_11(void) = ReturnIndirection : &:r68_9, ~mu68_4 -# 68| v68_12(void) = ReturnVoid : -# 68| v68_13(void) = UnmodeledUse : mu* -# 68| v68_14(void) = AliasedUse : ~mu68_4 -# 68| v68_15(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, ~mu68_4 +# 68| v68_12(void) = ReturnVoid : +# 68| v68_13(void) = UnmodeledUse : mu* +# 68| v68_14(void) = AliasedUse : ~mu68_4 +# 68| v68_15(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -752,7 +752,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_6 # 181| r181_4(int) = Load : &:r181_3, ~mu179_4 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_9(void) = ReturnIndirection : &:r179_7, ~mu179_4 +# 179| v179_9(void) = ReturnIndirection[p] : &:r179_7, ~mu179_4 # 179| r179_10(glval) = VariableAddress[#return] : # 179| v179_11(void) = ReturnValue : &:r179_10, m181_5 # 179| v179_12(void) = UnmodeledUse : mu* @@ -795,10 +795,10 @@ ssa.cpp: # 190| r190_6(unsigned int) = Load : &:r190_5, ~mu184_4 # 186| mu186_1(unknown) = InlineAsm : ~mu184_4, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 192| v192_1(void) = NoOp : -# 184| v184_21(void) = ReturnIndirection : &:r184_7, ~mu184_4 -# 184| v184_22(void) = ReturnIndirection : &:r184_11, ~mu184_4 -# 184| v184_23(void) = ReturnIndirection : &:r184_15, ~mu184_4 -# 184| v184_24(void) = ReturnIndirection : &:r184_19, ~mu184_4 +# 184| v184_21(void) = ReturnIndirection[a] : &:r184_7, ~mu184_4 +# 184| v184_22(void) = ReturnIndirection[b] : &:r184_11, ~mu184_4 +# 184| v184_23(void) = ReturnIndirection[c] : &:r184_15, ~mu184_4 +# 184| v184_24(void) = ReturnIndirection[d] : &:r184_19, ~mu184_4 # 184| v184_25(void) = ReturnVoid : # 184| v184_26(void) = UnmodeledUse : mu* # 184| v184_27(void) = AliasedUse : ~mu184_4 @@ -856,8 +856,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_15(void) = ReturnIndirection : &:r198_7, ~mu198_4 -# 198| v198_16(void) = ReturnIndirection : &:r198_11, ~mu198_4 +# 198| v198_15(void) = ReturnIndirection[str1] : &:r198_7, ~mu198_4 +# 198| v198_16(void) = ReturnIndirection[str2] : &:r198_11, ~mu198_4 # 198| r198_17(glval) = VariableAddress[#return] : # 198| v198_18(void) = ReturnValue : &:r198_17, m202_4 # 198| v198_19(void) = UnmodeledUse : mu* @@ -1099,7 +1099,7 @@ ssa.cpp: # 251| r251_2(glval) = VariableAddress[dst] : # 251| r251_3(char *) = Load : &:r251_2, m248_11 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_11(void) = ReturnIndirection : &:r247_7, ~mu247_4 +# 247| v247_11(void) = ReturnIndirection[src] : &:r247_7, ~mu247_4 # 247| r247_12(glval) = VariableAddress[#return] : # 247| v247_13(void) = ReturnValue : &:r247_12, m251_4 # 247| v247_14(void) = UnmodeledUse : mu* From 68097116b0cac1bbc45e3e8bfac287edd4ab390a Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 7 Feb 2020 15:51:23 -0800 Subject: [PATCH 018/459] C++:autoformat --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index e357c96782b..c224bbc3271 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -54,9 +54,7 @@ class ReturnNode extends InstructionNode { Instruction primary; ReturnNode() { - exists(ReturnValueInstruction ret | - instr = ret.getReturnValue() and primary = ret - ) + exists(ReturnValueInstruction ret | instr = ret.getReturnValue() and primary = ret) or exists(ReturnIndirectionInstruction rii | instr = rii.getSideEffectOperand().getAnyDef() and primary = rii From 8db3651dfd51d518dbe0b2cbed33a6120db555b0 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 12 Feb 2020 16:38:23 +0000 Subject: [PATCH 019/459] Add draft introductions and create map topic for Python --- .../learn-ql/python/ql-for-python.rst | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/docs/language/learn-ql/python/ql-for-python.rst b/docs/language/learn-ql/python/ql-for-python.rst index 680c0c374b5..6321f64eefb 100644 --- a/docs/language/learn-ql/python/ql-for-python.rst +++ b/docs/language/learn-ql/python/ql-for-python.rst @@ -8,30 +8,33 @@ CodeQL for Python introduce-libraries-python functions statements-expressions - control-flow - control-flow-graph - taint-tracking pointsto-type-infer + control-flow + taint-tracking -The following tutorials and worked examples are designed to help you learn how to write effective and efficient queries for Python projects. You should work through these topics in the order displayed. +Experiment and learn how to write effective and efficient queries for Python projects. -- `Basic Python query `__ describes how to write and run queries using LGTM. +:doc:`CodeQL libraries for Python ` +--------------------------------------------------------------- +Overview of the standard CodeQL libraries for writing CodeQL queries on Python code. -- :doc:`Introducing the CodeQL libraries for Python ` introduces the standard libraries used to write queries for Python code. +:doc:`Functions in Python ` +-------------------------------------- +Functions are key building blocks of Python code bases. You can find functions and identify calls to them using syntactic classes from the standard CodeQL library. -- :doc:`Tutorial: Functions ` demonstrates how to write queries using the standard CodeQL library classes for Python functions. +:doc:`Expressions and statements in Python ` +-------------------------------------------------------------------- +Expressions define a value. Statements represent a command or action. You can explore how they are used in a code base using syntactic classes from the standard CodeQL library. -- :doc:`Tutorial: Statements and expressions ` demonstrates how to write queries using the standard CodeQL library classes for Python statements and expressions. +:doc:`Pointer analysis and type inference in Python ` +-------------------------------------------------------------------------- +At run time, each Python expression has a value with an associated type. You can learn how an expression behaves at run time using type-inference classes from the standard CodeQL library. -- :doc:`Tutorial: Control flow ` demonstrates how to write queries using the standard CodeQL library classes for Python control flow. +:doc:`Analyzing control flow in Python ` +------------------------------------------------------ +You can write CodeQL queries to explore the control flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. -- :doc:`Tutorial: Points-to analysis and type inference ` demonstrates how to write queries using the standard CodeQL library classes for Python type inference. +:doc:`Analyzing data flow and tracking tainted data in Python ` +------------------------------------------------------------------------------- +You can use CodeQL to track the flow of data through a Python program to its use. Tracking user-controlled, or tainted, data is a key technique for security researchers. -- :doc:`Taint tracking and data flow analysis in Python ` demonstrates how to write queries using the standard taint tracking and data flow libraries for Python. - -Other resources ---------------- - -- For examples of how to query common Python elements, see the `Python cookbook `__. -- For the queries used in LGTM, display a `Python query `__ and click **Open in query console** to see the code used to find alerts. -- For more information about the library for Python see the `CodeQL library for Python `__. From 39ba3dedc168e0012388223b3d39e618b4cb41e3 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 12 Feb 2020 17:16:31 +0000 Subject: [PATCH 020/459] Fix build failure by moving control-flow image --- docs/language/learn-ql/python/control-flow-graph.rst | 9 --------- docs/language/learn-ql/python/control-flow.rst | 8 +++++++- 2 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 docs/language/learn-ql/python/control-flow-graph.rst diff --git a/docs/language/learn-ql/python/control-flow-graph.rst b/docs/language/learn-ql/python/control-flow-graph.rst deleted file mode 100644 index 099c252784b..00000000000 --- a/docs/language/learn-ql/python/control-flow-graph.rst +++ /dev/null @@ -1,9 +0,0 @@ -Python control flow graph -========================= - -:doc:`Back to tutorial: control flow analysis ` - -|Python control flow graph| - -.. |Python control flow graph| image:: ../../images/python-flow-graph.png - diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index fc41f59c933..bbabc8f32e2 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -19,7 +19,13 @@ To show why this complex relation is required consider the following Python code finally: close_resource() -There are many paths through the above code. There are three different paths through the call to ``close_resource();`` one normal path, one path that breaks out of the loop, and one path where an exception is raised by ``might_raise()``. (An annotated flow graph can be seen :doc:`here `.) +There are many paths through the above code. There are three different paths through the call to ``close_resource();`` one normal path, one path that breaks out of the loop, and one path where an exception is raised by ``might_raise()``. + +An annotated flow graph: + +|Python control flow graph| + +.. |Python control flow graph| image:: ../../images/python-flow-graph.png The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find unreachable code. There is one ``ControlFlowNode`` per path through any ``AstNode`` and any ``AstNode`` that is unreachable has no paths flowing through it. Therefore, any ``AstNode`` without a corresponding ``ControlFlowNode`` is unreachable. From 1d5971f8eca714bc36e3366a1c3772ae194ed44d Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 12 Feb 2020 13:29:21 -0800 Subject: [PATCH 021/459] C++: accept test changes from extractor update --- cpp/ql/test/library-tests/ir/ir/PrintAST.expected | 6 +++--- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 7778ebb76c0..343ffc27db5 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -5753,9 +5753,9 @@ ir.cpp: # 851| 0: [VariableDeclarationEntry] definition of d # 851| Type = [Struct] PolymorphicDerived # 851| init: [Initializer] initializer for d -# 851| expr: [ConstructorCall] call to PolymorphicDerived -# 851| Type = [VoidType] void -# 851| ValueCategory = prvalue +#-----| expr: [ConstructorCall] call to PolymorphicDerived +#-----| Type = [VoidType] void +#-----| ValueCategory = prvalue # 853| 2: [DeclStmt] declaration # 853| 0: [VariableDeclarationEntry] definition of pb # 853| Type = [PointerType] PolymorphicBase * diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index b291aaebd1a..1e14f92d0a6 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -4328,10 +4328,10 @@ ir.cpp: #-----| mu0_4(PolymorphicBase) = ^IndirectMayWriteSideEffect[-1] : &:r850_1 # 851| r851_1(glval) = VariableAddress[d] : # 851| mu851_2(PolymorphicDerived) = Uninitialized[d] : &:r851_1 -# 851| r851_3(glval) = FunctionAddress[PolymorphicDerived] : -# 851| v851_4(void) = Call : func:r851_3, this:r851_1 -# 851| mu851_5(unknown) = ^CallSideEffect : ~mu849_4 -# 851| mu851_6(PolymorphicDerived) = ^IndirectMayWriteSideEffect[-1] : &:r851_1 +#-----| r0_5(glval) = FunctionAddress[PolymorphicDerived] : +#-----| v0_6(void) = Call : func:r0_5, this:r851_1 +#-----| mu0_7(unknown) = ^CallSideEffect : ~mu849_4 +#-----| mu0_8(PolymorphicDerived) = ^IndirectMayWriteSideEffect[-1] : &:r851_1 # 853| r853_1(glval) = VariableAddress[pb] : # 853| r853_2(glval) = VariableAddress[b] : # 853| r853_3(PolymorphicBase *) = CopyValue : r853_2 From c846f536c48ef77a1c1a301f0dadd2849ed3c655 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Thu, 13 Feb 2020 12:56:45 +0000 Subject: [PATCH 022/459] Remove numbering --- docs/language/ql-handbook/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/language/ql-handbook/index.rst b/docs/language/ql-handbook/index.rst index 701d7d02237..a1e28bbaec4 100644 --- a/docs/language/ql-handbook/index.rst +++ b/docs/language/ql-handbook/index.rst @@ -21,7 +21,6 @@ Table of contents ***************** .. toctree:: - :numbered: 3 :maxdepth: 3 predicates @@ -42,4 +41,4 @@ Index and search **************** * :ref:`genindex` -* :ref:`search` +* :ref:`search` \ No newline at end of file From 2ce1ad1818bea56da053cf667008d2a14b5fb70a Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Thu, 13 Feb 2020 12:57:17 +0000 Subject: [PATCH 023/459] Rename "QLDoc specification" to "QLDoc comment specification" --- docs/language/ql-handbook/lexical-syntax.rst | 2 +- docs/language/ql-spec/index.rst | 2 +- docs/language/ql-spec/qldoc.rst | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/language/ql-handbook/lexical-syntax.rst b/docs/language/ql-handbook/lexical-syntax.rst index d5f152e829e..e25f5d266fa 100644 --- a/docs/language/ql-handbook/lexical-syntax.rst +++ b/docs/language/ql-handbook/lexical-syntax.rst @@ -19,7 +19,7 @@ All standard one-line and multiline comments, as described in the `QL language s compiler and are only visible in the source code. You can also write another kind of comment, namely **QLDoc comments**. These comments describe QL entities and are displayed as pop-up information in QL editors. For information about QLDoc -comments, see the `QLDoc specification `_. +comments, see the `QLDoc comment specification `_. The following example uses these three different kinds of comments:: diff --git a/docs/language/ql-spec/index.rst b/docs/language/ql-spec/index.rst index 4cbdc834936..e132d3ecac5 100644 --- a/docs/language/ql-spec/index.rst +++ b/docs/language/ql-spec/index.rst @@ -6,7 +6,7 @@ QL specifications For a formal specification of the QL language, including a description of syntax, terminology, and other technical details, please consult the QL language specification. -For information on the terminology and syntax used in QLDoc comments, please consult the QLDoc specification. +For information on the terminology and syntax used in QLDoc comments, please consult the QLDoc comment specification. .. toctree:: :maxdepth: 2 diff --git a/docs/language/ql-spec/qldoc.rst b/docs/language/ql-spec/qldoc.rst index 62987574c12..a17a7eadb60 100644 --- a/docs/language/ql-spec/qldoc.rst +++ b/docs/language/ql-spec/qldoc.rst @@ -1,5 +1,5 @@ -QLDoc specification -=================== +QLDoc comment specification +=========================== This document is a specification for QLDoc comments in QL source files. From c5eec307133dcbe7cf0defb4470338826609876b Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Thu, 13 Feb 2020 14:45:07 +0000 Subject: [PATCH 024/459] Tidy up QLDoc spec --- docs/language/ql-spec/qldoc.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/language/ql-spec/qldoc.rst b/docs/language/ql-spec/qldoc.rst index a17a7eadb60..d2ca924598e 100644 --- a/docs/language/ql-spec/qldoc.rst +++ b/docs/language/ql-spec/qldoc.rst @@ -1,7 +1,12 @@ QLDoc comment specification =========================== -This document is a specification for QLDoc comments in QL source files. +This document is a formal specification for QLDoc comments. + +About QLDoc comments +-------------------- + +You can provide documentation for a QL entity by adding a QLDoc comment in the source file. The QLDoc comment is displayed as pop-up information in QL editors, for example when you hover over a predicate name. Notation -------- @@ -36,7 +41,7 @@ Content The content of a QLDoc comment is interpreted as standard Markdown, with the following extensions: -- Fenced code blocks using \`s. +- Fenced code blocks using backticks. - Automatic interpretation of links and email addresses. - Use of appropriate characters for ellipses, dashes, apostrophes, and quotes. From 38e40622f180615b62d1aee3aa1a26aba5b7c47d Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Tue, 18 Feb 2020 12:03:51 +0000 Subject: [PATCH 025/459] Update topic titles and update map topic as discussed with JF and SP --- .../language/learn-ql/python/control-flow.rst | 6 ++-- docs/language/learn-ql/python/functions.rst | 4 ++- .../python/introduce-libraries-python.rst | 6 ++-- .../learn-ql/python/pointsto-type-infer.rst | 6 ++-- .../learn-ql/python/ql-for-python.rst | 30 ++----------------- .../python/statements-expressions.rst | 4 ++- .../learn-ql/python/taint-tracking.rst | 6 ++-- 7 files changed, 24 insertions(+), 38 deletions(-) diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index bbabc8f32e2..a8361e48222 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -1,5 +1,7 @@ -Tutorial: Control flow analysis -=============================== +Analyzing control flow in Python +================================ + +You can write CodeQL queries to explore the control flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. To analyze the `Control-flow graph `__ of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index c3c8a5e6eac..a50c61f3241 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -1,6 +1,8 @@ -Tutorial: Functions +Functions in Python =================== +Functions are key building blocks of Python code bases. You can find functions and identify calls to them using syntactic classes from the standard CodeQL library. + This example uses the standard CodeQL class ``Function`` (see :doc:`Introducing the Python libraries `). Finding all functions called "get..." diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 54276aedd8e..bfe2429d4dd 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -1,7 +1,7 @@ -Introducing the CodeQL libraries for Python -=========================================== +CodeQL library for Python +========================= -There is an extensive library for analyzing CodeQL databases extracted from Python projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: +Overview of the extensive library you use to analyze databases generated from Python code bases. This library uses classes with abstractions and predicates to present the data in an object-oriented form. This abstraction makes it easier for you to write queries. .. code-block:: ql diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index 7ae9368d02c..b0e68cf4278 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -1,5 +1,7 @@ -Tutorial: Points-to analysis and type inference -=============================================== +Pointer analysis and type inference in Python +============================================= + +At run time, each Python expression has a value with an associated type. You can learn how an expression behaves at run time using type-inference classes from the standard CodeQL library. This topic contains worked examples of how to write queries using the standard CodeQL library classes for Python type inference. diff --git a/docs/language/learn-ql/python/ql-for-python.rst b/docs/language/learn-ql/python/ql-for-python.rst index 6321f64eefb..b4f47e8a70c 100644 --- a/docs/language/learn-ql/python/ql-for-python.rst +++ b/docs/language/learn-ql/python/ql-for-python.rst @@ -1,9 +1,11 @@ CodeQL for Python ================= +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Python code bases. + .. toctree:: :glob: - :hidden: + :maxdepth: 2 introduce-libraries-python functions @@ -12,29 +14,3 @@ CodeQL for Python control-flow taint-tracking -Experiment and learn how to write effective and efficient queries for Python projects. - -:doc:`CodeQL libraries for Python ` ---------------------------------------------------------------- -Overview of the standard CodeQL libraries for writing CodeQL queries on Python code. - -:doc:`Functions in Python ` --------------------------------------- -Functions are key building blocks of Python code bases. You can find functions and identify calls to them using syntactic classes from the standard CodeQL library. - -:doc:`Expressions and statements in Python ` --------------------------------------------------------------------- -Expressions define a value. Statements represent a command or action. You can explore how they are used in a code base using syntactic classes from the standard CodeQL library. - -:doc:`Pointer analysis and type inference in Python ` --------------------------------------------------------------------------- -At run time, each Python expression has a value with an associated type. You can learn how an expression behaves at run time using type-inference classes from the standard CodeQL library. - -:doc:`Analyzing control flow in Python ` ------------------------------------------------------- -You can write CodeQL queries to explore the control flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. - -:doc:`Analyzing data flow and tracking tainted data in Python ` -------------------------------------------------------------------------------- -You can use CodeQL to track the flow of data through a Python program to its use. Tracking user-controlled, or tainted, data is a key technique for security researchers. - diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index d3b4e68af6c..0d8667cf491 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -1,6 +1,8 @@ -Tutorial: Statements and expressions +Expressions and statements in Python ==================================== +Expressions define a value. Statements represent a command or action. You can explore how they are used in a code base using syntactic classes from the standard CodeQL library. + Statements ---------- diff --git a/docs/language/learn-ql/python/taint-tracking.rst b/docs/language/learn-ql/python/taint-tracking.rst index 2ea24369bf4..3982f2d6bb4 100644 --- a/docs/language/learn-ql/python/taint-tracking.rst +++ b/docs/language/learn-ql/python/taint-tracking.rst @@ -1,5 +1,7 @@ -Taint tracking and data flow analysis in Python -=============================================== +Analyzing data flow and tracking tainted data in Python +======================================================= + +You can use CodeQL to track the flow of data through a Python program to its use. Tracking user-controlled, or tainted, data is a key technique for security researchers. Overview -------- From 8ab4cebc9b1c78b5c6eb8c289e1c53150a009b4f Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Tue, 18 Feb 2020 12:16:33 +0000 Subject: [PATCH 026/459] Add reusable for other resources and make 'Further reading' section --- docs/language/learn-ql/python/control-flow.rst | 8 ++++---- docs/language/learn-ql/python/functions.rst | 11 +++++++---- .../learn-ql/python/introduce-libraries-python.rst | 12 ++++++++---- .../language/learn-ql/python/pointsto-type-infer.rst | 9 +++++---- .../learn-ql/python/statements-expressions.rst | 11 +++++++---- docs/language/learn-ql/python/taint-tracking.rst | 10 ++++++---- docs/language/reusables/python-other-resources.rst | 3 +++ 7 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 docs/language/reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index a8361e48222..9405e8cacc2 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -108,8 +108,8 @@ Combining these conditions we get: ➤ `See this in the query console `__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis which is covered in the next tutorial. -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the tutorial topic :doc:`Taint tracking and data flow analysis in Python `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Analyzing data flow and tracking tainted data in Python `" +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index a50c61f3241..6e7b5aa9a4d 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -78,8 +78,11 @@ The ``Call`` class represents calls in Python. The ``Call.getFunc()`` predicate Due to the dynamic nature of Python, this query will select any call of the form ``eval(...)`` regardless of whether it is a call to the built-in function ``eval`` or not. In a later tutorial we will see how to use the type-inference library to find calls to the built-in function ``eval`` regardless of name of the variable called. -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Statements and expressions `, :doc:`Control flow `, and :doc:`Points-to analysis and type inference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Expressions and statements in Python `" +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index bfe2429d4dd..8526db5ce69 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -329,8 +329,12 @@ Summary These classes are explained in more detail in :doc:`Tutorial: Taint tracking and data flow analysis in Python `. -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Functions `, :doc:`Statements and expressions `, :doc:`Control flow `, :doc:`Points-to analysis and type inference `, and :doc:`Taint tracking and data flow analysis in Python `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Functions in Python `" +- ":doc:`Expressions and statements in Python `" +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index b0e68cf4278..4397ac7ddce 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -227,8 +227,9 @@ Then we can use ``Value.getACall()`` to identify calls to the ``eval`` function, ➤ `See this in the query console `__. This accurately identifies calls to the builtin ``eval`` function even when they are referred to using an alternative name. Any false positive results with calls to other ``eval`` functions, reported by the original query, have been eliminated. -What next? ----------- +Further reading +--------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Read a description of the CodeQL database in :doc:`What's in a CodeQL database? <../database>` +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 0d8667cf491..ff59aec4e7b 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -273,8 +273,11 @@ Here is the relevant part of the class hierarchy: - ``Class`` - ``Function`` -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Control flow ` and :doc:`Points-to analysis and type inference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Functions in Python `" +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/taint-tracking.rst b/docs/language/learn-ql/python/taint-tracking.rst index 3982f2d6bb4..f759d16debe 100644 --- a/docs/language/learn-ql/python/taint-tracking.rst +++ b/docs/language/learn-ql/python/taint-tracking.rst @@ -253,8 +253,10 @@ which defines the simplest possible taint kind class, ``HardcodedValue``, and cu } } -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Control flow ` and :doc:`Points-to analysis and type inference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/reusables/python-other-resources.rst b/docs/language/reusables/python-other-resources.rst new file mode 100644 index 00000000000..9668db06d6d --- /dev/null +++ b/docs/language/reusables/python-other-resources.rst @@ -0,0 +1,3 @@ +- "`QL language handbook `__" +- `Python cookbook queries `__ in the Semmle wiki +- `Python queries in action `__ on LGTM.com From 8a44f51fc5ed8bf727319347ee833360f24602c0 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Tue, 18 Feb 2020 13:18:02 +0000 Subject: [PATCH 027/459] Bring headings more into line with content models --- .../language/learn-ql/python/control-flow.rst | 13 +++-- docs/language/learn-ql/python/functions.rst | 2 +- .../python/introduce-libraries-python.rst | 44 +++++++++------- .../learn-ql/python/pointsto-type-infer.rst | 3 +- .../python/statements-expressions.rst | 52 ++++++------------- .../learn-ql/python/taint-tracking.rst | 23 ++++---- 6 files changed, 66 insertions(+), 71 deletions(-) diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index 9405e8cacc2..ae0328fff44 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -31,7 +31,8 @@ An annotated flow graph: The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find unreachable code. There is one ``ControlFlowNode`` per path through any ``AstNode`` and any ``AstNode`` that is unreachable has no paths flowing through it. Therefore, any ``AstNode`` without a corresponding ``ControlFlowNode`` is unreachable. -**Unreachable AST nodes** +Example finding unreachable AST nodes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ql @@ -43,7 +44,8 @@ The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find u ➤ `See this in the query console `__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements: -**Unreachable statements** +Example finding unreachable statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ql @@ -60,8 +62,8 @@ The ``BasicBlock`` class The ``BasicBlock`` class represents a `basic block `__ of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as what can reach what and what `dominates `__ what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. -Example: Finding mutually exclusive basic blocks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding mutually exclusive basic blocks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Suppose we have the following Python code: @@ -92,7 +94,8 @@ However, by that definition, two basic blocks are mutually exclusive if they are Combining these conditions we get: -**Mutually exclusive blocks within the same function** +Example finding mutually exclusive blocks within the same function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ql diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index 6e7b5aa9a4d..f9c43623263 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -3,7 +3,7 @@ Functions in Python Functions are key building blocks of Python code bases. You can find functions and identify calls to them using syntactic classes from the standard CodeQL library. -This example uses the standard CodeQL class ``Function`` (see :doc:`Introducing the Python libraries `). +These examples use the standard CodeQL class `Function `__. For more information, see :doc:`Introducing the Python libraries `. Finding all functions called "get..." ------------------------------------- diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 8526db5ce69..624814705c7 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -3,15 +3,15 @@ CodeQL library for Python Overview of the extensive library you use to analyze databases generated from Python code bases. This library uses classes with abstractions and predicates to present the data in an object-oriented form. This abstraction makes it easier for you to write queries. +About the CodeQL library for Python +----------------------------------- + +The CodeQL library for each programming language is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: + .. code-block:: ql import python -The rest of this tutorial summarizes the contents of the standard libraries for Python. We recommend that you read this and then work through the practical examples in the tutorials shown at the end of the page. - -Overview of the library ------------------------ - The CodeQL library for Python incorporates a large number of classes. Each class corresponds either to one kind of entity in Python source code or to an entity that can be derived from the source code using static analysis. These classes can be divided into four categories: - **Syntactic** - classes that represent entities in the Python source code. @@ -20,16 +20,16 @@ The CodeQL library for Python incorporates a large number of classes. Each class - **Taint tracking** - classes that represent the source, sinks and kinds of taint used to implement taint-tracking queries. Syntactic classes -~~~~~~~~~~~~~~~~~ +----------------- -This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an `Abstract syntax tree `__ (AST). The root of each AST is a ``Module``. +This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. For more information, see `Abstract syntax tree `__. -`Symbolic information `__ is attached to the AST in the form of variables (represented by the class ``Variable``). +Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Symbolic information `__. Scope ^^^^^ -A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes (`Module `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``. +A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes (`Module `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``). - ``Scope`` @@ -153,8 +153,8 @@ Both forms are equivalent. Using the positive expression, the whole query looks ➤ `See this in the query console `__. Many projects include pass-only ``except`` blocks. -Summary -^^^^^^^ +Summary of syntactic classes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The most commonly used standard classes in the syntactic part of the library are organized as follows: @@ -237,11 +237,14 @@ Other - ``Comment`` – A comment Control flow classes -~~~~~~~~~~~~~~~~~~~~ +-------------------- This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into `basic blocks `__. -As an example, we might want to find the longest sequence of code without any branches. A ``BasicBlock`` is, by definition, a sequence of code without any branches, so we just need to find the longest ``BasicBlock``. +Example +^^^^^^^ + +If we want to find the longest sequence of code without any branches, we need to consider control flow. A ``BasicBlock`` is, by definition, a sequence of code without any branches, so we just need to find the longest ``BasicBlock``. First of all we introduce a simple predicate ``bb_length()`` which relates ``BasicBlock``\ s to their length. @@ -289,7 +292,12 @@ The classes in the control-flow part of the library are: Type-inference classes ---------------------- -The CodeQL library for Python also supplies some classes for accessing the inferred types of values. The classes ``Value`` and ``ClassValue`` allow you to query the possible classes that an expression may have at runtime. For example, which ``ClassValue``\ s are iterable can be determined using the query: +The CodeQL library for Python also supplies some classes for accessing the inferred types of values. The classes ``Value`` and ``ClassValue`` allow you to query the possible classes that an expression may have at runtime. + +Example +^^^^^^^ + +For example, which ``ClassValue``\ s are iterable can be determined using the query: **Find iterable "ClassValue"s** @@ -304,7 +312,7 @@ The CodeQL library for Python also supplies some classes for accessing the infer ➤ `See this in the query console `__ This query returns a list of classes for the projects analyzed. If you want to include the results for `builtin classes `__, which do not have any Python source code, show the non-source results. Summary -~~~~~~~ +^^^^^^^ - `Value `__ @@ -312,7 +320,7 @@ Summary - ``CallableValue`` - ``ModuleValue`` -These classes are explained in more detail in :doc:`Tutorial: Points-to analysis and type inference `. +For more information about these classes, see :doc:`Pointer analysis and type inference in Python `. Taint-tracking classes ---------------------- @@ -321,12 +329,12 @@ The CodeQL library for Python also supplies classes to specify taint-tracking an Summary -~~~~~~~ +^^^^^^^ - `TaintKind `__ - `Configuration `__ -These classes are explained in more detail in :doc:`Tutorial: Taint tracking and data flow analysis in Python `. +For more information about these classes, see :doc:`Analyzing data flow and tracking tainted data in Python `. Further reading diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index 4397ac7ddce..e0fbdac403c 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -3,6 +3,7 @@ Pointer analysis and type inference in Python At run time, each Python expression has a value with an associated type. You can learn how an expression behaves at run time using type-inference classes from the standard CodeQL library. + This topic contains worked examples of how to write queries using the standard CodeQL library classes for Python type inference. The ``Value`` class @@ -11,7 +12,7 @@ The ``Value`` class The ``Value`` class and its subclasses ``FunctionValue``, ``ClassValue``, and ``ModuleValue`` represent the values an expression may hold at runtime. Summary -~~~~~~~ +^^^^^^^ Class hierarchy for ``Value``: diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index ff59aec4e7b..2a7a57c33b5 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -39,13 +39,11 @@ Here is the full class hierarchy: - ``While`` – A ``while`` statement - ``With`` – A ``with`` statement -Example: Finding redundant 'global' statements -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding redundant 'global' statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ``global`` statement in Python declares a variable with a global (module-level) scope, when it would otherwise be local. Using the ``global`` statement outside a class or function is redundant as the variable is already global. -**Finding redundant global statements** - .. code-block:: ql import python @@ -58,13 +56,11 @@ The ``global`` statement in Python declares a variable with a global (module-lev The line: ``g.getScope() instanceof Module`` ensures that the ``Scope`` of ``Global g`` is a ``Module``, rather than a class or function. -Example: Finding 'if' statements with redundant branches --------------------------------------------------------- +Example finding 'if' statements with redundant branches +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ An ``if`` statement where one branch is composed of just ``pass`` statements could be simplified by negating the condition and dropping the ``else`` clause. -**An 'if' statement that could be simplified** - .. code-block:: python if cond(): @@ -72,9 +68,7 @@ An ``if`` statement where one branch is composed of just ``pass`` statements cou else: do_something -To find statements like this we can run the following query: - -**Find 'if' statements with empty branches** +To find statements like this that could be simplified we can write a query. .. code-block:: ql @@ -133,8 +127,8 @@ Each kind of Python expression has its own class. Here is the full class hierarc - ``Yield`` – A ``yield`` expression - ``YieldFrom`` – A ``yield from`` expression (Python 3.3+) -Example: Finding comparisons to integer or string literals using 'is' -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding comparisons to integer or string literals using 'is' +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Python implementations commonly cache small integers and single character strings, which means that comparisons such as the following often work correctly, but this is not guaranteed and we might want to check for them. @@ -143,9 +137,7 @@ Python implementations commonly cache small integers and single character string x is 10 x is "A" -We can check for these as follows: - -**Find comparisons to integer or string literals using** ``is`` +We can check for these using a query. .. code-block:: ql @@ -166,15 +158,11 @@ The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` che We have to use ``cmp.getOp(0)`` and ``cmp.getComparator(0)``\ as there is no ``cmp.getOp()`` or ``cmp.getComparator()``. The reason for this is that a ``Compare`` expression can have multiple operators. For example, the expression ``3 < x < 7`` has two operators and two comparators. You use ``cmp.getComparator(0)`` to get the first comparator (in this example the ``3``) and ``cmp.getComparator(1)`` to get the second comparator (in this example the ``7``). -Example: Duplicates in dictionary literals -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding duplicates in dictionary literals +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If there are duplicate keys in a Python dictionary, then the second key will overwrite the first, which is almost certainly a mistake. We can find these duplicates with CodeQL, but the query is more complex than previous examples and will require us to write a ``predicate`` as a helper. -Here is the query: - -**Find duplicate dictionary keys** - .. code-block:: ql import python @@ -206,12 +194,10 @@ is equivalent to The short version is usually used as this is easier to read. -Example: Finding Java-style getters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding Java-style getters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Returning to the example from :doc:`Tutorial: Functions `, the query identified all methods with a single line of code and a name starting with ``get``: - -**Basic: Find Java-style getters** +Returning to the example from :doc:`Tutorial: Functions `, the query identified all methods with a single line of code and a name starting with ``get``. .. code-block:: ql @@ -222,9 +208,7 @@ Returning to the example from :doc:`Tutorial: Functions `, the query and count(f.getAStmt()) = 1 select f, "This function is (probably) a getter." -This basic query can be improved by checking that the one line of code is of the form ``return self.attr`` - -**Improved: Find Java-style getters** +This basic query can be improved by checking that the one line of code is a Java-style getter of the form ``return self.attr``. .. code-block:: ql @@ -238,21 +222,17 @@ This basic query can be improved by checking that the one line of code is of the ➤ `See this in the query console `__. Of the demo projects on LGTM.com, only the *openstack/nova* project has examples of functions that appear to be Java-style getters. -In this query, the condition: - .. code-block:: ql ret = f.getStmt(0) and ret.getValue() = attr -checks that the first line in the method is a return statement and that the expression returned (``ret.getValue()``) is an ``Attribute`` expression. Note that the equality ``ret.getValue() = attr`` means that ``ret.getValue()`` is restricted to ``Attribute``\ s, since ``attr`` is an ``Attribute``. - -The condition: +This condition checks that the first line in the method is a return statement and that the expression returned (``ret.getValue()``) is an ``Attribute`` expression. Note that the equality ``ret.getValue() = attr`` means that ``ret.getValue()`` is restricted to ``Attribute``\ s, since ``attr`` is an ``Attribute``. .. code-block:: ql attr.getObject() = self and self.getId() = "self" -checks that the value of the attribute (the expression to the left of the dot in ``value.attr``) is an access to a variable called ``"self"``. +This condition checks that the value of the attribute (the expression to the left of the dot in ``value.attr``) is an access to a variable called ``"self"``. Class and function definitions ------------------------------ diff --git a/docs/language/learn-ql/python/taint-tracking.rst b/docs/language/learn-ql/python/taint-tracking.rst index f759d16debe..90cb20b5517 100644 --- a/docs/language/learn-ql/python/taint-tracking.rst +++ b/docs/language/learn-ql/python/taint-tracking.rst @@ -3,8 +3,8 @@ Analyzing data flow and tracking tainted data in Python You can use CodeQL to track the flow of data through a Python program to its use. Tracking user-controlled, or tainted, data is a key technique for security researchers. -Overview --------- +About data flow and taint tracking +---------------------------------- Taint tracking is used to analyze how potentially insecure, or 'tainted' data flows throughout a program at runtime. You can use taint tracking to find out whether user-controlled input can be used in a malicious way, @@ -16,12 +16,12 @@ For example, in the assignment ``dir = path + "/"``, if ``path`` is tainted then even though there is no data flow from ``path`` to ``path + "/"``. Separate CodeQL libraries have been written to handle 'normal' data flow and taint tracking in :doc:`C/C++ <../cpp/dataflow>`, :doc:`C# <../csharp/dataflow>`, :doc:`Java <../java/dataflow>`, and :doc:`JavaScript <../javascript/dataflow>`. You can access the appropriate classes and predicates that reason about these different modes of data flow by importing the appropriate library in your query. -In Python analysis, we can use the same taint tracking library to model both 'normal' data flow and taint flow, but we are still able make the distinction between steps that preserve value and those that don't by defining additional data flow properties. +In Python analysis, we can use the same taint tracking library to model both 'normal' data flow and taint flow, but we are still able make the distinction between steps that preserve values and those that don't by defining additional data flow properties. For further information on data flow and taint tracking with CodeQL, see :doc:`Introduction to data flow <../intro-to-data-flow>`. -Fundamentals of taint tracking and data flow analysis -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Fundamentals of taint tracking using data flow analysis +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The taint tracking library is in the `TaintTracking `__ module. Any taint tracking or data flow analysis query has three explicit components, one of which is optional, and an implicit component. @@ -41,7 +41,7 @@ The kind of taint determines which non-value-preserving steps are possible, in a In the above example ``dir = path + "/"``, taint flows from ``path`` to ``dir`` if the taint represents a string, but not if the taint is ``None``. Limitations -~~~~~~~~~~~ +^^^^^^^^^^^ Although taint tracking is a powerful technique, it is worth noting that it depends on the underlying data flow graphs. Creating a data flow graph that is both accurate and covers a large enough part of a program is a challenge, @@ -81,6 +81,9 @@ A simple taint tracking query has the basic form: where config.hasFlow(src, sink) select sink, "Alert message, including reference to $@.", src, "string describing the source" +Example +^^^^^^^ + As a contrived example, here is a query that looks for flow from a HTTP request to a function called ``"unsafe"``. The sources are predefined and accessed by importing library ``semmle.python.web.HttpRequest``. The sink is defined by using a custom ``TaintTracking::Sink`` class. @@ -128,8 +131,8 @@ The sink is defined by using a custom ``TaintTracking::Sink`` class. -Implementing path queries -~~~~~~~~~~~~~~~~~~~~~~~~~ +Converting a taint-tracking query to a path query +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Although the taint tracking query above tells which sources flow to which sinks, it doesn't tell us how. For that we need a path query. @@ -204,8 +207,8 @@ Thus, our example query becomes: -Custom taint kinds and flows ----------------------------- +Tracking custom taint kinds and flows +------------------------------------- In the above examples, we have assumed the existence of a suitable ``TaintKind``, but sometimes it is necessary to model the flow of other objects, such as database connections, or ``None``. From 74d93ba70436e27588ab0955d16232084b18bc72 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Tue, 18 Feb 2020 16:05:01 +0000 Subject: [PATCH 028/459] Tidy up some references --- docs/language/learn-ql/python/control-flow.rst | 6 +++--- docs/language/learn-ql/python/functions.rst | 2 +- .../learn-ql/python/introduce-libraries-python.rst | 12 +++++------- .../language/learn-ql/python/pointsto-type-infer.rst | 8 +++----- .../learn-ql/python/statements-expressions.rst | 4 ++-- docs/language/learn-ql/python/taint-tracking.rst | 6 +++--- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index ae0328fff44..ec2d602d492 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -3,7 +3,7 @@ Analyzing control flow in Python You can write CodeQL queries to explore the control flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. -To analyze the `Control-flow graph `__ of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. +To analyze the control-flow graph of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. For more information, see `Control-flow graph `__ in Wikipedia. The ``ControlFlowNode`` class ----------------------------- @@ -55,12 +55,12 @@ Example finding unreachable statements where not exists(s.getAFlowNode()) select s -➤ `See this in the query console `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard query: `Unreachable code `__. +➤ `See this in the query console `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard query: unreachable code. For more information, see `Unreachable code `__ on LGTM.com. The ``BasicBlock`` class ------------------------ -The ``BasicBlock`` class represents a `basic block `__ of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as what can reach what and what `dominates `__ what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. +The ``BasicBlock`` class represents a basic block of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as, what can reach what, and what dominates what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. For more information, see `basic block `__ and `dominates `__ on Wikipedia. Example finding mutually exclusive basic blocks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index f9c43623263..2924a77f910 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -57,7 +57,7 @@ We can modify the query further to include only methods whose body consists of a and count(f.getAStmt()) = 1 select f, "This function is (probably) a getter." -➤ `See this in the query console `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in :doc:`Tutorial: Statements and expressions `. +➤ `See this in the query console `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Tutorial: Statements and expressions `." Finding a call to a specific function ------------------------------------- diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 624814705c7..e29e25edb4b 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -22,9 +22,7 @@ The CodeQL library for Python incorporates a large number of classes. Each class Syntactic classes ----------------- -This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. For more information, see `Abstract syntax tree `__. - -Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Symbolic information `__. +This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Abstract syntax tree `__ and `Symbolic information `__ in Wikipedia. Scope ^^^^^ @@ -239,7 +237,7 @@ Other Control flow classes -------------------- -This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into `basic blocks `__. +This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into basic blocks. For more information, see `basic blocks `__ in Wikipedia. Example ^^^^^^^ @@ -309,7 +307,7 @@ For example, which ``ClassValue``\ s are iterable can be determined using the qu where cls.hasAttribute("__iter__") select cls -➤ `See this in the query console `__ This query returns a list of classes for the projects analyzed. If you want to include the results for `builtin classes `__, which do not have any Python source code, show the non-source results. +➤ `See this in the query console `__ This query returns a list of classes for the projects analyzed. If you want to include the results for ``builtin`` classes, which do not have any Python source code, show the non-source results. For more information, see `builtin classes `__ in the Python documentation. Summary ^^^^^^^ @@ -320,7 +318,7 @@ Summary - ``CallableValue`` - ``ModuleValue`` -For more information about these classes, see :doc:`Pointer analysis and type inference in Python `. +For more information about these classes, see ":doc:`Pointer analysis and type inference in Python `." Taint-tracking classes ---------------------- @@ -334,7 +332,7 @@ Summary - `TaintKind `__ - `Configuration `__ -For more information about these classes, see :doc:`Analyzing data flow and tracking tainted data in Python `. +For more information about these classes, see ":doc:`Analyzing data flow and tracking tainted data in Python `". Further reading diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index e0fbdac403c..ddee31da7c0 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -25,9 +25,7 @@ Class hierarchy for ``Value``: Points-to analysis and type inference ------------------------------------- -Points-to analysis, sometimes known as `pointer analysis `__, allows us to determine which objects an expression may "point to" at runtime. - -`Type inference `__ allows us to infer what the types (classes) of an expression may be at runtime. +Points-to analysis, sometimes known as pointer analysis, allows us to determine which objects an expression may "point to" at runtime. Type inference allows us to infer what the types (classes) of an expression may be at runtime. For more information, see `pointer analysis `__ and `Type inference `__ on Wikipedia. The predicate ``ControlFlowNode.pointsTo(...)`` shows which object a control flow node may "point to" at runtime. @@ -126,7 +124,7 @@ Combining the parts of the query we get this: ) select t, ex1, ex2 -➤ `See this in the query console `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard query: `Unreachable 'except' block `__. +➤ `See this in the query console `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard query: Unreachable 'except' block. For more information, see `Unreachable 'except' block `__ on LGTM.com. .. pull-quote:: @@ -186,7 +184,7 @@ The ``Value`` class has a method ``getACall()`` which allows us to find calls to If we wish to restrict the callables to actual functions we can use the ``FunctionValue`` class, which is a subclass of ``Value`` and corresponds to function objects in Python, in much the same way as the ``ClassValue`` class corresponds to class objects in Python. -Returning to an example from :doc:`Tutorial: Functions `, we wish to find calls to the ``eval`` function. +Returning to an example from ":doc:`Tutorial: Functions `," we wish to find calls to the ``eval`` function. The original query looked this: diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 2a7a57c33b5..016fdb11a3e 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -178,7 +178,7 @@ If there are duplicate keys in a Python dictionary, then the second key will ove and k1 != k2 and same_key(k1, k2) select k1, "Duplicate key in dict literal" -➤ `See this in the query console `__. When we ran this query on LGTM.com, the source code of the *saltstack/salt* project contained an example of duplicate dictionary keys. The results were also highlighted as alerts by the standard `Duplicate key in dict literal `__ query. Two of the other demo projects on LGTM.com refer to duplicate dictionary keys in library files. +➤ `See this in the query console `__. When we ran this query on LGTM.com, the source code of the *saltstack/salt* project contained an example of duplicate dictionary keys. The results were also highlighted as alerts by the standard "Duplicate key in dict literal" query. Two of the other demo projects on LGTM.com refer to duplicate dictionary keys in library files. For more information, see `Duplicate key in dict literal `__ on LGTM.com. The supporting predicate ``same_key`` checks that the keys have the same identifier. Separating this part of the logic into a supporting predicate, instead of directly including it in the query, makes it easier to understand the query as a whole. The casts defined in the predicate restrict the expression to the type specified and allow predicates to be called on the type that is cast-to. For example: @@ -197,7 +197,7 @@ The short version is usually used as this is easier to read. Example finding Java-style getters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Returning to the example from :doc:`Tutorial: Functions `, the query identified all methods with a single line of code and a name starting with ``get``. +Returning to the example from ":doc:`Tutorial: Functions `," the query identified all methods with a single line of code and a name starting with ``get``. .. code-block:: ql diff --git a/docs/language/learn-ql/python/taint-tracking.rst b/docs/language/learn-ql/python/taint-tracking.rst index 90cb20b5517..4f892b437a5 100644 --- a/docs/language/learn-ql/python/taint-tracking.rst +++ b/docs/language/learn-ql/python/taint-tracking.rst @@ -18,7 +18,7 @@ even though there is no data flow from ``path`` to ``path + "/"``. Separate CodeQL libraries have been written to handle 'normal' data flow and taint tracking in :doc:`C/C++ <../cpp/dataflow>`, :doc:`C# <../csharp/dataflow>`, :doc:`Java <../java/dataflow>`, and :doc:`JavaScript <../javascript/dataflow>`. You can access the appropriate classes and predicates that reason about these different modes of data flow by importing the appropriate library in your query. In Python analysis, we can use the same taint tracking library to model both 'normal' data flow and taint flow, but we are still able make the distinction between steps that preserve values and those that don't by defining additional data flow properties. -For further information on data flow and taint tracking with CodeQL, see :doc:`Introduction to data flow <../intro-to-data-flow>`. +For further information on data flow and taint tracking with CodeQL, see ":doc:`Introduction to data flow <../intro-to-data-flow>`." Fundamentals of taint tracking using data flow analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -231,8 +231,8 @@ The ``TaintKind`` itself is just a string (a QL string, not a CodeQL entity repr which provides methods to extend flow and allow the kind of taint to change along the path. The ``TaintKind`` class has many predicates allowing flow to be modified. This simplest ``TaintKind`` does not override any predicates, meaning that it only flows as opaque data. -An example of this is the `Hard-coded credentials query `_, -which defines the simplest possible taint kind class, ``HardcodedValue``, and custom source and sink classes. +An example of this is the "Hard-coded credentials" query, +which defines the simplest possible taint kind class, ``HardcodedValue``, and custom source and sink classes. For more information, see `Hard-coded credentials `_ on LGTM.com. .. code-block:: ql From fdbc74825e1b2862d26d1c06fa19a82b73aa6c93 Mon Sep 17 00:00:00 2001 From: Alistair Christie Date: Tue, 18 Feb 2020 16:34:55 +0000 Subject: [PATCH 029/459] Java topics - change titles & add intros --- docs/language/learn-ql/java/annotations.rst | 8 ++++---- docs/language/learn-ql/java/ast-class-reference.rst | 6 ++++-- docs/language/learn-ql/java/call-graph.rst | 6 ++++-- docs/language/learn-ql/java/dataflow.rst | 6 ++++-- docs/language/learn-ql/java/expressions-statements.rst | 6 ++++-- docs/language/learn-ql/java/introduce-libraries-java.rst | 6 ++++-- docs/language/learn-ql/java/javadoc.rst | 6 ++++-- docs/language/learn-ql/java/ql-for-java.rst | 2 ++ docs/language/learn-ql/java/source-locations.rst | 6 ++++-- docs/language/learn-ql/java/types-class-hierarchy.rst | 6 ++++-- 10 files changed, 38 insertions(+), 20 deletions(-) diff --git a/docs/language/learn-ql/java/annotations.rst b/docs/language/learn-ql/java/annotations.rst index 9fbb70776c4..5e5d2f826e6 100644 --- a/docs/language/learn-ql/java/annotations.rst +++ b/docs/language/learn-ql/java/annotations.rst @@ -1,11 +1,11 @@ -Tutorial: Annotations -===================== +Annotations in Java +=================== + +CodeQL databases of Java projects contain information about all annotations attached to program elements. Overview -------- -CodeQL databases of Java projects contain information about all annotations attached to program elements. - Annotations are represented by the following CodeQL classes: - The class ``Annotatable`` represents all entities that may have an annotation attached to them (that is, packages, reference types, fields, methods, and local variables). diff --git a/docs/language/learn-ql/java/ast-class-reference.rst b/docs/language/learn-ql/java/ast-class-reference.rst index 268b95acac5..aac764411ad 100644 --- a/docs/language/learn-ql/java/ast-class-reference.rst +++ b/docs/language/learn-ql/java/ast-class-reference.rst @@ -1,5 +1,7 @@ -AST class reference -=================== +Abstract syntax tree classes in Java +==================================== + +CodeQL has a large selection of classes for working with Java code. .. _Expr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Expr.html .. _Stmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index cfaa33cad9f..07460b73190 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -1,5 +1,7 @@ -Tutorial: Navigating the call graph -=================================== +Navigating the call graph +========================= + +CodeQL provides an API for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used. Call graph API -------------- diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index bddc206aa82..360e3f9ab31 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -1,11 +1,13 @@ Analyzing data flow in Java -============================ +=========================== + +You can use CodeQL to track the flow of data through a Java program to its use. Overview -------- This topic describes how data flow analysis is implemented in the CodeQL libraries for Java and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. +The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index 25d605b18b8..9fad2aa6faf 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -1,5 +1,7 @@ -Tutorial: Expressions and statements -==================================== +Expressions and statements in Java +================================== + +You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow. Overview -------- diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index cf8a2f3c27c..b7529c1d2e7 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -1,5 +1,7 @@ -Introducing the CodeQL libraries for Java -========================================= +CodeQL library for Java +======================= + +When you need to analyze a Java program, you can make use of the large collection of classes in the Java library for CodeQL. Overview -------- diff --git a/docs/language/learn-ql/java/javadoc.rst b/docs/language/learn-ql/java/javadoc.rst index bd0a11b9132..03968a44230 100644 --- a/docs/language/learn-ql/java/javadoc.rst +++ b/docs/language/learn-ql/java/javadoc.rst @@ -1,5 +1,7 @@ -Tutorial: Javadoc -================= +Javadoc +======= + +You can use CodeQL to find errors in Javadoc comments in Java code. Overview -------- diff --git a/docs/language/learn-ql/java/ql-for-java.rst b/docs/language/learn-ql/java/ql-for-java.rst index aa26c5ba6bb..606eef327cd 100644 --- a/docs/language/learn-ql/java/ql-for-java.rst +++ b/docs/language/learn-ql/java/ql-for-java.rst @@ -1,6 +1,8 @@ CodeQL for Java =============== +You can use CodeQL to explore Java programs and quickly find variants of security vulnerabilities and bugs. + .. toctree:: :glob: :hidden: diff --git a/docs/language/learn-ql/java/source-locations.rst b/docs/language/learn-ql/java/source-locations.rst index 6e29777fab9..ac9a9232568 100644 --- a/docs/language/learn-ql/java/source-locations.rst +++ b/docs/language/learn-ql/java/source-locations.rst @@ -1,5 +1,7 @@ -Tutorial: Working with source locations -======================================= +Working with source locations +============================= + +You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. Overview -------- diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index a438f111cab..2940da96cd6 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -1,5 +1,7 @@ -Tutorial: Types and the class hierarchy -======================================= +Types in Java +============= + +You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues. Overview -------- From 2a5ac2e8294280451ee6b847a93dfc4557873fa2 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Tue, 18 Feb 2020 16:50:48 +0000 Subject: [PATCH 030/459] Fix failing Sphinx tests --- docs/language/learn-ql/python/control-flow.rst | 1 + docs/language/learn-ql/python/functions.rst | 1 + docs/language/learn-ql/python/introduce-libraries-python.rst | 1 + docs/language/learn-ql/python/pointsto-type-infer.rst | 1 + docs/language/learn-ql/python/statements-expressions.rst | 1 + docs/language/learn-ql/python/taint-tracking.rst | 3 ++- 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index ec2d602d492..6fb7e8d919f 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -115,4 +115,5 @@ Further reading --------------- - ":doc:`Analyzing data flow and tracking tainted data in Python `" + .. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index 2924a77f910..a412b57e72a 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -85,4 +85,5 @@ Further reading - ":doc:`Pointer analysis and type inference in Python `" - ":doc:`Analyzing control flow in Python `" - ":doc:`Analyzing data flow and tracking tainted data in Python `" + .. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index e29e25edb4b..d5c7ab77aab 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -343,4 +343,5 @@ Further reading - ":doc:`Pointer analysis and type inference in Python `" - ":doc:`Analyzing control flow in Python `" - ":doc:`Analyzing data flow and tracking tainted data in Python `" + .. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index ddee31da7c0..b64762c1d0d 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -231,4 +231,5 @@ Further reading - ":doc:`Analyzing control flow in Python `" - ":doc:`Analyzing data flow and tracking tainted data in Python `" + .. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 016fdb11a3e..2b857f4f9a2 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -260,4 +260,5 @@ Further reading - ":doc:`Pointer analysis and type inference in Python `" - ":doc:`Analyzing control flow in Python `" - ":doc:`Analyzing data flow and tracking tainted data in Python `" + .. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/taint-tracking.rst b/docs/language/learn-ql/python/taint-tracking.rst index 4f892b437a5..ff9eff4ed6f 100644 --- a/docs/language/learn-ql/python/taint-tracking.rst +++ b/docs/language/learn-ql/python/taint-tracking.rst @@ -132,7 +132,7 @@ The sink is defined by using a custom ``TaintTracking::Sink`` class. Converting a taint-tracking query to a path query -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Although the taint tracking query above tells which sources flow to which sinks, it doesn't tell us how. For that we need a path query. @@ -262,4 +262,5 @@ Further reading - ":doc:`Pointer analysis and type inference in Python `" - ":doc:`Analyzing control flow in Python `" - ":doc:`Analyzing data flow and tracking tainted data in Python `" + .. include:: ../../reusables/python-other-resources.rst From ff876aaedf0815f4fab688a1f66dc7a59c69d2e3 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 18 Feb 2020 09:48:21 -0800 Subject: [PATCH 031/459] C++: Accept test output with IR enabled --- .../Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected | 1 + .../CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected | 2 ++ 2 files changed, 3 insertions(+) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 3b73052432d..167c8d419fa 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -3,3 +3,4 @@ | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets | | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets | +| funcsLocal.c:58:9:58:10 | e1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected index 594f572f25f..4659e258bcb 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected @@ -8,3 +8,5 @@ | test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value | | test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value | | test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value | +| test.cpp:31:7:31:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | Uncontrolled value | +| test.cpp:37:7:37:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | Uncontrolled value | From 2245d64c5207fef2a49c039f1533f1146dd32419 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 17 Feb 2020 09:57:38 +0000 Subject: [PATCH 032/459] docs: tidy up ql-for-cpp --- docs/language/learn-ql/cpp/ql-for-cpp.rst | 38 +++-------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/docs/language/learn-ql/cpp/ql-for-cpp.rst b/docs/language/learn-ql/cpp/ql-for-cpp.rst index b1596c7de92..3a82d43b662 100644 --- a/docs/language/learn-ql/cpp/ql-for-cpp.rst +++ b/docs/language/learn-ql/cpp/ql-for-cpp.rst @@ -1,9 +1,11 @@ CodeQL for C/C++ ================ + +Learn how to write queries using the standard CodeQL libraries for C and C++. + .. toctree:: - :glob: - :hidden: + :maxdepth: 1 introduce-libraries-cpp function-classes @@ -12,42 +14,10 @@ CodeQL for C/C++ dataflow private-field-initialization zero-space-terminator - -These topics provide an overview of the CodeQL libraries for C/C++ and show examples of how to write queries that use them. - -- `Basic C/C++ query `__ describes how to write and run queries using LGTM. - -- :doc:`Introducing the CodeQL libraries for C/C++ ` introduces the standard libraries used to write queries for C and C++ code. - -- :doc:`Tutorial: Function classes ` demonstrates how to write queries using the standard CodeQL library classes for C/C++ functions. - -- :doc:`Tutorial: Expressions, types and statements ` demonstrates how to write queries using the standard CodeQL library classes for C/C++ expressions, types and statements. - -- :doc:`Tutorial: Conversions and classes ` demonstrates how to write queries using the standard CodeQL library classes for C/C++ conversions and classes. - -- :doc:`Tutorial: Analyzing data flow in C/C++ ` demonstrates how to write queries using the standard data flow and taint tracking libraries for C/C++. - -- :doc:`Example: Checking that constructors initialize all private fields ` works through the development of a query. It introduces recursive predicates and shows the typical workflow used to refine a query. - -- :doc:`Example: Checking for allocations equal to strlen(string) without space for a null terminator ` shows how a query to detect this particular buffer issue was developed. - -Advanced libraries ----------------------------------- - -.. toctree:: - :hidden: - guards range-analysis value-numbering-hash-cons -- :doc:`Using the guards library in C and C++ ` demonstrates how to identify conditional expressions that control the execution of other code and what guarantees they provide. - -- :doc:`Using range analysis for C and C++ ` demonstrates how to determine constant upper and lower bounds and possible overflow or underflow of expressions. - -- :doc:`Using hash consing and value numbering for C and C++ ` demonstrates how to recognize expressions that are syntactically identical or compute the same value at runtime. - - Other resources --------------- From d3eb5334b82ea3d862bc9fb353c614d0213336d7 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 17 Feb 2020 10:02:58 +0000 Subject: [PATCH 033/459] docs: update titles, some links, add intros --- .../language/learn-ql/cpp/conversions-classes.rst | 13 +++++-------- docs/language/learn-ql/cpp/dataflow.rst | 9 ++++----- docs/language/learn-ql/cpp/expressions-types.rst | 9 ++++----- docs/language/learn-ql/cpp/function-classes.rst | 12 +++++++----- docs/language/learn-ql/cpp/guards.rst | 2 ++ .../learn-ql/cpp/introduce-libraries-cpp.rst | 15 ++++++++++----- .../learn-ql/cpp/private-field-initialization.rst | 8 +++++--- docs/language/learn-ql/cpp/range-analysis.rst | 2 ++ .../learn-ql/cpp/value-numbering-hash-cons.rst | 4 +++- .../learn-ql/cpp/zero-space-terminator.rst | 6 ++++-- 10 files changed, 46 insertions(+), 34 deletions(-) diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index 016efa50d67..98258f50c50 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -1,10 +1,7 @@ -Tutorial: Conversions and classes -================================= +Conversions and classes in C and C++ +==================================== -Overview --------- - -This topic contains worked examples of how to write queries using the CodeQL library classes for C/C++ conversions and classes. +You can use the standard CodeQL libraries for C and C++ to detect when the type of an expression is changed. Conversions ----------- @@ -227,7 +224,7 @@ What next? ---------- - Explore other ways of querying classes using examples from the `C/C++ cookbook `__. -- Take a look at the :doc:`Analyzing data flow in C/C++ ` tutorial. -- Try the worked examples in the following topics: :doc:`Example: Checking that constructors initialize all private fields `, and :doc:`Example: Checking for allocations equal to 'strlen(string)' without space for a null terminator `. +- Take a look at the :doc:`Analyzing data flow in C and C++ ` tutorial. +- Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases `, and :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index 686759c049f..1c29abcced1 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -1,8 +1,7 @@ -Analyzing data flow in C/C++ -============================ +Analyzing data flow in C and C++ +================================ -Overview --------- +You can use data-flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your code base. This topic describes how data flow analysis is implemented in the CodeQL libraries for C/C++ and includes examples to help you write your own data flow queries. The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. @@ -299,7 +298,7 @@ Exercise 4: Using the answers from 2 and 3, write a query which finds all global What next? ---------- -- Try the worked examples in the following topics: :doc:`Example: Checking that constructors initialize all private fields ` and :doc:`Example: Checking for allocations equal to 'strlen(string)' without space for a null terminator `. +- Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases ` and :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/cpp/expressions-types.rst b/docs/language/learn-ql/cpp/expressions-types.rst index 1595d594683..5b983676545 100644 --- a/docs/language/learn-ql/cpp/expressions-types.rst +++ b/docs/language/learn-ql/cpp/expressions-types.rst @@ -1,8 +1,7 @@ -Tutorial: Expressions, types and statements -=========================================== +Expressions, types, and statements in C and C++ +=============================================== -Overview --------- +You can use CodeQL to explore expressions, types, and statements in C and C++ code to find, for example, incorrect assignments. This topic contains worked examples of how to write queries using the standard CodeQL library classes for C/C++ expressions, types, and statements. @@ -136,6 +135,6 @@ What next? ---------- - Explore other ways of finding types and statements using examples from the C/C++ cookbook for `types `__ and `statements `__. -- Take a look at the :doc:`Conversions and classes ` and :doc:`Analyzing data flow in C/C++ ` tutorials. +- Take a look at the :doc:`Conversions and classes in C and C++ ` and :doc:`Analyzing data flow in C and C++ ` tutorials. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/cpp/function-classes.rst b/docs/language/learn-ql/cpp/function-classes.rst index 51f07a8d0f0..3f3350d8bb0 100644 --- a/docs/language/learn-ql/cpp/function-classes.rst +++ b/docs/language/learn-ql/cpp/function-classes.rst @@ -1,10 +1,12 @@ -Tutorial: Function classes -========================== +Functions in C and C++ +======================= + +You can use CodeQL to explore functions in C and C++ code. Overview -------- -The standard CodeQL library for C and C++ represents functions using the ``Function`` class (see :doc:`Introducing the C/C++ libraries `). +The standard CodeQL library for C and C++ represents functions using the ``Function`` class (see :doc:`CodeQL libraries for C and C++ `). The example queries in this topic explore some of the most useful library predicates for querying functions. @@ -26,7 +28,7 @@ This query is very general, so there are probably too many results to be interes Finding functions that are not called ------------------------------------- -It might be more interesting to find functions that are not called, using the standard CodeQL ``FunctionCall`` class from the **abstract syntax tree** category (see :doc:`Introducing the C/C++ libraries `). The ``FunctionCall`` class can be used to identify places where a function is actually used, and it is related to ``Function`` through the ``FunctionCall.getTarget()`` predicate. +It might be more interesting to find functions that are not called, using the standard CodeQL ``FunctionCall`` class from the **abstract syntax tree** category (see :doc:`CodeQL libraries for C and C++ `). The ``FunctionCall`` class can be used to identify places where a function is actually used, and it is related to ``Function`` through the ``FunctionCall.getTarget()`` predicate. .. code-block:: ql @@ -91,6 +93,6 @@ What next? ---------- - Explore other ways of finding functions using examples from the `C/C++ cookbook `__. -- Take a look at some of the other tutorials: :doc:`Expressions, types and statements `, :doc:`Conversions and classes `, and :doc:`Analyzing data flow in C/C++ `. +- Take a look at some other tutorials: :doc:`Expressions, types and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/cpp/guards.rst b/docs/language/learn-ql/cpp/guards.rst index f21a7f866e5..1c63267375e 100644 --- a/docs/language/learn-ql/cpp/guards.rst +++ b/docs/language/learn-ql/cpp/guards.rst @@ -1,6 +1,8 @@ Using the guards library in C and C++ ===================================== +You can use the CodeQL guards library to identify conditional expressions that control the execution of other code in C and C++ codebases. + Overview -------- diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 6bea8d40c2c..f96140a7e63 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -1,10 +1,13 @@ -Introducing the CodeQL libraries for C/C++ -========================================== +CodeQL libraries for C and C++ +============================== + +Explore the standard CodeQL libraries for C and C++. Overview -------- -There is an extensive library for analyzing CodeQL databases extracted from C/C++ projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``cpp.qll`` imports all the core C/C++ library modules, so you can include the complete library by beginning your query with: +There is an extensive library for analyzing CodeQL databases extracted from C/C++ projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. +The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``cpp.qll`` imports all the core C/C++ library modules, so you can include the complete library by beginning your query with: .. code-block:: ql @@ -12,7 +15,9 @@ There is an extensive library for analyzing CodeQL databases extracted from C/C+ The rest of this topic summarizes the available CodeQL classes and corresponding C/C++ constructs. -NOTE: You can find related classes and features using the query console's auto-complete feature. You can also press *F3* to jump to the definition of any element; library files are opened in new tabs in the console. +.. pull-quote:: Note + + You can find related classes and features using the query console's auto-complete feature. You can also press *F3* to jump to the definition of any element. Library files are opened in new tabs in the console. Summary of the library classes ------------------------------ @@ -522,6 +527,6 @@ This table lists `Preprocessor `, :doc:`Expressions, types and statements `, :doc:`Conversions and classes `, and :doc:`Analyzing data flow in C/C++ `. +- Experiment with the worked examples in the CodeQL for C/C++ topics: :doc:`Functions in C and C++ `, :doc:`Expressions, types, and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/cpp/private-field-initialization.rst b/docs/language/learn-ql/cpp/private-field-initialization.rst index 26b57660142..fead702e11f 100644 --- a/docs/language/learn-ql/cpp/private-field-initialization.rst +++ b/docs/language/learn-ql/cpp/private-field-initialization.rst @@ -1,5 +1,7 @@ -Example: Checking that constructors initialize all private fields -================================================================= +Refining a query to account for edge cases +========================================== + +You can improve the results generated by a CodeQL query by adding conditions to remove false positives caused by common edge cases. Overview -------- @@ -147,6 +149,6 @@ Finally we can simplify the query by using the `transitive closure operator `. +- Take a look at another example: :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/cpp/range-analysis.rst b/docs/language/learn-ql/cpp/range-analysis.rst index c60465e131d..52dbcb3aefe 100644 --- a/docs/language/learn-ql/cpp/range-analysis.rst +++ b/docs/language/learn-ql/cpp/range-analysis.rst @@ -1,6 +1,8 @@ Using range analysis for C and C++ ================================== +You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow. + Overview -------- diff --git a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst index e05f93dbae1..f7976162046 100644 --- a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst +++ b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst @@ -1,5 +1,7 @@ Hash consing and value numbering -================================================= +================================ + +You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases. Overview -------- diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index a9370f7828d..a834e6c3b36 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -1,5 +1,7 @@ -Example: Checking for allocations equal to ``strlen(string)`` without space for a null terminator -================================================================================================= +Detecting a potential buffer overflow +===================================== + +You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. Overview -------- From 6ff1c99ae330c02a4d4dd87aa4a1bb1884defe65 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 17 Feb 2020 15:08:30 +0000 Subject: [PATCH 034/459] docs: a few content updates --- docs/language/learn-ql/cpp/conversions-classes.rst | 8 ++++---- docs/language/learn-ql/cpp/dataflow.rst | 8 ++++---- docs/language/learn-ql/cpp/expressions-types.rst | 12 +++++------- docs/language/learn-ql/cpp/guards.rst | 6 +++--- .../learn-ql/cpp/introduce-libraries-cpp.rst | 6 +++--- .../learn-ql/cpp/private-field-initialization.rst | 10 +++++----- docs/language/learn-ql/cpp/range-analysis.rst | 6 ++---- .../learn-ql/cpp/value-numbering-hash-cons.rst | 9 +++------ docs/language/learn-ql/cpp/zero-space-terminator.rst | 2 +- 9 files changed, 30 insertions(+), 37 deletions(-) diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index 98258f50c50..fc087ae5c31 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -6,7 +6,9 @@ You can use the standard CodeQL libraries for C and C++ to detect when the type Conversions ----------- -Let us take a look at the ``Conversion`` class in the standard library: +In C and C++, conversions change the type of an expression. They may be implicit conversions generated by the compiler, or explicit conversions requested by the user. + +Let's take a look at the `Conversion `__ class in the standard library: - ``Expr`` @@ -22,8 +24,6 @@ Let us take a look at the ``Conversion`` class in the standard library: - ``ArrayToPointerConversion`` - ``VirtualMemberToFunctionPointerConversion`` -All conversions change the type of an expression. They may be implicit conversions (generated by the compiler) or explicit conversions (requested by the user). - Exploring the subexpressions of an assignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -218,7 +218,7 @@ Our last change is to use ``Function.isVirtual()`` to find cases where the base That completes the query. -There is a similar built-in LGTM `query `__ that finds classes in a C/C++ project with virtual functions but no virtual destructor. You can take a look at the code for this query by clicking **Open in query console** at the top of that page. +There is a similar built-in `query `__ on LGTM.com that finds classes in a C/C++ project with virtual functions but no virtual destructor. You can take a look at the code for this query by clicking **Open in query console** at the top of that page. What next? ---------- diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index 1c29abcced1..a620e8664bc 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -1,12 +1,12 @@ Analyzing data flow in C and C++ ================================ -You can use data-flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your code base. +You can use data-flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase. -This topic describes how data flow analysis is implemented in the CodeQL libraries for C/C++ and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. +About data flow +--------------- -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For more background information, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. Local data flow --------------- diff --git a/docs/language/learn-ql/cpp/expressions-types.rst b/docs/language/learn-ql/cpp/expressions-types.rst index 5b983676545..c88b5fc24db 100644 --- a/docs/language/learn-ql/cpp/expressions-types.rst +++ b/docs/language/learn-ql/cpp/expressions-types.rst @@ -3,10 +3,8 @@ Expressions, types, and statements in C and C++ You can use CodeQL to explore expressions, types, and statements in C and C++ code to find, for example, incorrect assignments. -This topic contains worked examples of how to write queries using the standard CodeQL library classes for C/C++ expressions, types, and statements. - -Expressions and types ---------------------- +Expressions and types in CodeQL +------------------------------- Each part of an expression in C becomes an instance of the ``Expr`` class. For example, the C code ``x = x + 1`` becomes an ``AssignExpr``, an ``AddExpr``, two instances of ``VariableAccess`` and a ``Literal``. All of these CodeQL classes extend ``Expr``. @@ -33,7 +31,7 @@ It is also worth noting that the query above would find this C code: yPtr = NULL; -This is because the database contains a representation of the code base after the preprocessor transforms have run (for more information, see `Database generation `__). This means that any macro invocations, such as the ``NULL`` define used here, are expanded during the creation of the database. If you want to write queries about macros then there are some special library classes that have been designed specifically for this purpose (for example, the ``Macro``, ``MacroInvocation`` classes and predicates like ``Element.isInMacroExpansion()``). In this case, it is good that macros are expanded, but we do not want to find assignments to pointers. +This is because the database contains a representation of the code base after the preprocessor transforms have run. This means that any macro invocations, such as the ``NULL`` define used here, are expanded during the creation of the database. If you want to write queries about macros then there are some special library classes that have been designed specifically for this purpose (for example, the ``Macro``, ``MacroInvocation`` classes and predicates like ``Element.isInMacroExpansion()``). In this case, it is good that macros are expanded, but we do not want to find assignments to pointers. For more information, see `Database generation `__ on LGTM.com. Finding assignments of 0 to an integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -60,8 +58,8 @@ This checks that the left side of the assignment has a type that is some kind of i = 0; -Statements ----------- +Statements in CodeQL +-------------------- We can refine the query further using statements. In this case we use the class ``ForStmt``: diff --git a/docs/language/learn-ql/cpp/guards.rst b/docs/language/learn-ql/cpp/guards.rst index 1c63267375e..35f185b8b49 100644 --- a/docs/language/learn-ql/cpp/guards.rst +++ b/docs/language/learn-ql/cpp/guards.rst @@ -3,8 +3,8 @@ Using the guards library in C and C++ You can use the CodeQL guards library to identify conditional expressions that control the execution of other code in C and C++ codebases. -Overview --------- +About the guards library +------------------------ The guards library (defined in ``semmle.code.cpp.controlflow.Guards``) provides a class `GuardCondition `__ representing Boolean values that are used to make control flow decisions. A ``GuardCondition`` is considered to guard a basic block if the block can only be reached if the ``GuardCondition`` is evaluated a certain way. For instance, in the following code, ``x < 10`` is a ``GuardCondition``, and it guards all the code before the return statement. @@ -22,7 +22,7 @@ A ``GuardCondition`` is considered to guard a basic block if the block can only The ``controls`` predicate ------------------------------------------------- +-------------------------- The ``controls`` predicate helps determine which blocks are only run when the ``GuardCondition`` evaluates a certain way. ``guard.controls(block, testIsTrue)`` holds if ``block`` is only entered if the value of this condition is ``testIsTrue``. diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index f96140a7e63..2985bc24a67 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -3,8 +3,8 @@ CodeQL libraries for C and C++ Explore the standard CodeQL libraries for C and C++. -Overview --------- +About the CodeQL libraries for C and C++ +---------------------------------------- There is an extensive library for analyzing CodeQL databases extracted from C/C++ projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``cpp.qll`` imports all the core C/C++ library modules, so you can include the complete library by beginning your query with: @@ -19,7 +19,7 @@ The rest of this topic summarizes the available CodeQL classes and corresponding You can find related classes and features using the query console's auto-complete feature. You can also press *F3* to jump to the definition of any element. Library files are opened in new tabs in the console. -Summary of the library classes +Commonly-used library classes ------------------------------ The most commonly used standard library classes are listed below. The listing is broken down by functionality. Each library class is annotated with a C/C++ construct it corresponds to. diff --git a/docs/language/learn-ql/cpp/private-field-initialization.rst b/docs/language/learn-ql/cpp/private-field-initialization.rst index fead702e11f..f7bc180cd4b 100644 --- a/docs/language/learn-ql/cpp/private-field-initialization.rst +++ b/docs/language/learn-ql/cpp/private-field-initialization.rst @@ -6,10 +6,10 @@ You can improve the results generated by a CodeQL query by adding conditions to Overview -------- -This topic describes how a C++ query was developed. The example introduces recursive predicates and demonstrates the typical workflow used to refine a query. For a full overview of the topics available for learning to write queries for C/C++ code, see :doc:`CodeQL for C/C++ `. +This topic describes how a C++ query was developed. The example introduces recursive predicates and demonstrates the typical workflow used to refine a query. For a full overview of the topics available for learning to write queries for C/C++ code, see :doc:`CodeQL for C and C++ `. -Problem—finding every private field and checking for initialization -------------------------------------------------------------------- +Finding every private field and checking for initialization +----------------------------------------------------------- Writing a query to check if a constructor initializes all private fields seems like a simple problem, but there are several edge cases to account for. @@ -102,7 +102,7 @@ You may also wish to consider methods called by constructors that assign to the int m_value; }; -This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls (see `Recursion `__ for more information). +This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls. For more information, see `Recursion `__ in the QL language handbook. .. code-block:: ql @@ -126,7 +126,7 @@ This case can be excluded by creating a recursive predicate. The recursive predi Refinement 4—simplifying the query ---------------------------------- -Finally we can simplify the query by using the `transitive closure operator `__. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. +Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see `transitive closures `__ in the QL language handbook. .. code-block:: ql diff --git a/docs/language/learn-ql/cpp/range-analysis.rst b/docs/language/learn-ql/cpp/range-analysis.rst index 52dbcb3aefe..ba324e86ac9 100644 --- a/docs/language/learn-ql/cpp/range-analysis.rst +++ b/docs/language/learn-ql/cpp/range-analysis.rst @@ -3,10 +3,8 @@ Using range analysis for C and C++ You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow. -Overview --------- - -Range analysis determines upper and lower bounds for an expression. +About the range analysis library +-------------------------------- The range analysis library (defined in ``semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis``) provides a set of predicates for determining constant upper and lower bounds on expressions, as well as recognizing integer overflows. For performance, the library performs automatic widening and therefore may not provide the tightest possible bounds. diff --git a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst index f7976162046..c4b16bcfd57 100644 --- a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst +++ b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst @@ -3,15 +3,12 @@ Hash consing and value numbering You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases. -Overview --------- +About the hash consing and value numbering libraries +---------------------------------------------------- In C and C++ databases, each node in the abstract syntax tree is represented by a separate object. This allows both analysis and results display to refer to specific appearances of a piece of syntax. However, it is frequently useful to determine whether two expressions are equivalent, either syntactically or semantically. -The `hash consing `__ library (defined in ``semmle.code.cpp.valuenumbering.HashCons``) provides a mechanism for identifying expressions that have the same syntactic structure. The `global value numbering `__ library (defined in ``semmle.code.cpp.valuenumbering.GlobalValueNumbering``) provides a mechanism for identifying expressions that compute the same value at runtime. - -Both libraries partition the expressions in each function into equivalence classes represented by objects. Each ``HashCons`` object represents a set of expressions with identical parse trees, while ``GVN`` objects represent sets of expressions that will always compute the same value. - +The hash consing library (defined in ``semmle.code.cpp.valuenumbering.HashCons``) provides a mechanism for identifying expressions that have the same syntactic structure. The global value numbering library (defined in ``semmle.code.cpp.valuenumbering.GlobalValueNumbering``) provides a mechanism for identifying expressions that compute the same value at runtime. Both libraries partition the expressions in each function into equivalence classes represented by objects. Each ``HashCons`` object represents a set of expressions with identical parse trees, while ``GVN`` objects represent sets of expressions that will always compute the same value. For more information, see `hash consing `__ and `value numbering `__ on Wikipedia. Example C code -------------- diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index a834e6c3b36..4611559f204 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -100,7 +100,7 @@ When you have defined the basic query then you can refine the query to include f Improving the query using the 'SSA' library ------------------------------------------- -The ``SSA`` library represents variables in `static single assignment `__ (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. +The ``SSA`` library represents variables in static single assignment (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. For more information, see `static single assignment `__ on Wikipedia. Including examples where the string size is stored before use ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From fab7955c75fe934d2838b6aa086e9bf57b7e5e6e Mon Sep 17 00:00:00 2001 From: Alistair Christie Date: Wed, 19 Feb 2020 12:50:06 +0000 Subject: [PATCH 035/459] Make small editorial changes --- docs/language/learn-ql/java/annotations.rst | 32 ++++++++-------- docs/language/learn-ql/java/call-graph.rst | 10 ++--- docs/language/learn-ql/java/dataflow.rst | 36 +++++++++--------- .../learn-ql/java/expressions-statements.rst | 20 +++++----- .../java/introduce-libraries-java.rst | 20 +++++----- docs/language/learn-ql/java/javadoc.rst | 38 +++++++++---------- .../learn-ql/java/source-locations.rst | 32 ++++++++-------- .../learn-ql/java/types-class-hierarchy.rst | 14 +++---- 8 files changed, 101 insertions(+), 101 deletions(-) diff --git a/docs/language/learn-ql/java/annotations.rst b/docs/language/learn-ql/java/annotations.rst index 5e5d2f826e6..26ade9dbd80 100644 --- a/docs/language/learn-ql/java/annotations.rst +++ b/docs/language/learn-ql/java/annotations.rst @@ -3,17 +3,17 @@ Annotations in Java CodeQL databases of Java projects contain information about all annotations attached to program elements. -Overview --------- +About working with annotations +------------------------------ -Annotations are represented by the following CodeQL classes: +Annotations are represented by these CodeQL classes: - The class ``Annotatable`` represents all entities that may have an annotation attached to them (that is, packages, reference types, fields, methods, and local variables). - The class ``AnnotationType`` represents a Java annotation type, such as ``java.lang.Override``; annotation types are interfaces. - The class ``AnnotationElement`` represents an annotation element, that is, a member of an annotation type. - The class ``Annotation`` represents an annotation such as ``@Override``; annotation values can be accessed through member predicate ``getValue``. -As an example, recall that the Java standard library defines an annotation ``SuppressWarnings`` that instructs the compiler not to emit certain kinds of warnings. It is defined as follows: +For example, the Java standard library defines an annotation ``SuppressWarnings`` that instructs the compiler not to emit certain kinds of warnings: .. code-block:: java @@ -25,7 +25,7 @@ As an example, recall that the Java standard library defines an annotation ``Sup ``SuppressWarnings`` is represented as an ``AnnotationType``, with ``value`` as its only ``AnnotationElement``. -A typical usage of ``SuppressWarnings`` would be the following annotation to prevent a warning about using raw types: +A typical usage of ``SuppressWarnings`` would be this annotation for preventing a warning about using raw types: .. code-block:: java @@ -37,7 +37,7 @@ A typical usage of ``SuppressWarnings`` would be the following annotation to pre The expression ``@SuppressWarnings("rawtypes")`` is represented as an ``Annotation``. The string literal ``"rawtypes"`` is used to initialize the annotation element ``value``, and its value can be extracted from the annotation by means of the ``getValue`` predicate. -We could then write the following query to find all ``@SuppressWarnings`` annotations attached to constructors, and return both the annotation itself and the value of its ``value`` element: +We could then write this query to find all ``@SuppressWarnings`` annotations attached to constructors, and return both the annotation itself and the value of its ``value`` element: .. code-block:: ql @@ -69,9 +69,9 @@ As another example, this query finds all annotation types that only have a singl Example: Finding missing ``@Override`` annotations -------------------------------------------------- -In newer versions of Java, it is recommended (though not required) to annotate methods that override another method with an ``@Override`` annotation. These annotations, which are checked by the compiler, serve as documentation, and also help you avoid accidental overloading where overriding was intended. +In newer versions of Java, it's recommended (though not required) that you annotate methods that override another method with an ``@Override`` annotation. These annotations, which are checked by the compiler, serve as documentation, and also help you avoid accidental overloading where overriding was intended. -For example, consider the following example program: +For example, consider this example program: .. code-block:: java @@ -89,9 +89,9 @@ For example, consider the following example program: Here, both ``Sub1.m`` and ``Sub2.m`` override ``Super.m``, but only ``Sub1.m`` is annotated with ``@Override``. -We will now develop a query for finding methods like ``Sub2.m`` that should be annotated with ``@Override``, but are not. +We'll now develop a query for finding methods like ``Sub2.m`` that should be annotated with ``@Override``, but are not. -As a first step, let us write a query that finds all ``@Override`` annotations. Annotations are expressions, so their type can be accessed using ``getType``. Annotation types, on the other hand, are interfaces, so their qualified name can be queried using ``hasQualifiedName``. Therefore we can implement the query as follows: +As a first step, let's write a query that finds all ``@Override`` annotations. Annotations are expressions, so their type can be accessed using ``getType``. Annotation types, on the other hand, are interfaces, so their qualified name can be queried using ``hasQualifiedName``. Therefore we can implement the query like this: .. code-block:: ql @@ -111,7 +111,7 @@ As always, it is a good idea to try this query on a CodeQL database for a Java p } } -This makes it very easy to write our query for finding methods that override another method, but do not have an ``@Override`` annotation: we use predicate ``overrides`` to find out whether one method overrides another, and predicate ``getAnAnnotation`` (available on any ``Annotatable``) to retrieve some annotation. +This makes it very easy to write our query for finding methods that override another method, but don't have an ``@Override`` annotation: we use predicate ``overrides`` to find out whether one method overrides another, and predicate ``getAnAnnotation`` (available on any ``Annotatable``) to retrieve some annotation. .. code-block:: ql @@ -122,14 +122,14 @@ This makes it very easy to write our query for finding methods that override ano not overriding.getAnAnnotation() instanceof OverrideAnnotation select overriding, "Method overrides another method, but does not have an @Override annotation." -➤ `See this in the query console `__. In practice, this query may yield many results from compiled library code, which are not very interesting. Therefore, it is a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available. +➤ `See this in the query console `__. In practice, this query may yield many results from compiled library code, which aren't very interesting. It's therefore a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available. Example: Finding calls to deprecated methods -------------------------------------------- As another example, we can write a query that finds calls to methods marked with a ``@Deprecated`` annotation. -For example, consider the following example program: +For example, consider this example program: .. code-block:: java @@ -147,7 +147,7 @@ For example, consider the following example program: Here, both ``A.m`` and ``A.n`` are marked as deprecated. Methods ``n`` and ``r`` both call ``m``, but note that ``n`` itself is deprecated, so we probably should not warn about this call. -Like in the previous example, we start by defining a class for representing ``@Deprecated`` annotations: +As in the previous example, we'll start by defining a class for representing ``@Deprecated`` annotations: .. code-block:: ql @@ -235,8 +235,8 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress ➤ `See this in the query console `__. It's fairly common for projects to contain calls to methods that appear to be deprecated. -What next? ----------- +Further reading +--------------- - Take a look at some of the other tutorials: :doc:`Tutorial: Javadoc ` and :doc:`Tutorial: Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index 07460b73190..6f4862c8fc6 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -58,7 +58,7 @@ Class ``Call`` provides two call graph navigation predicates: For instance, in our example ``getCallee`` of the second call in ``Client.main`` would return ``Super.getX``. At runtime, though, this call would actually invoke ``Sub.getX``. -Class ``Callable`` defines a large number of member predicates; for our purposes, the two most important ones are as follows: +Class ``Callable`` defines a large number of member predicates; for our purposes, the two most important ones are: - ``calls(Callable target)`` succeeds if this callable contains a call whose callee is ``target``. - ``polyCalls(Callable target)`` succeeds if this callable may call ``target`` at runtime; this is the case if it contains a call whose callee is either ``target`` or a method that ``target`` overrides. @@ -86,7 +86,7 @@ Given this API, we can easily write a query that finds methods that are not call We have to use ``polyCalls`` instead of ``calls`` here: we want to be reasonably sure that ``callee`` is not called, either directly or via overriding. -Running this query on a typical Java project results in lots of hits in the Java standard library. This makes sense, since no single client program uses every method of the standard library. More generally, we may want to exclude methods and constructors from compiled libraries. We can use the predicate ``fromSource`` to check whether a compilation unit is a source file, and refine our query as follows: +Running this query on a typical Java project results in lots of hits in the Java standard library. This makes sense, since no single client program uses every method of the standard library. More generally, we may want to exclude methods and constructors from compiled libraries. We can use the predicate ``fromSource`` to check whether a compilation unit is a source file, and refine our query: .. code-block:: ql @@ -144,7 +144,7 @@ A further special case is non-public default constructors: in the singleton patt ➤ `See this in the query console `__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects. -Finally, on many Java projects there are methods that are invoked indirectly by reflection. Thus, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The QL Java library has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes: +Finally, on many Java projects there are methods that are invoked indirectly by reflection. So, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The QL Java library has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes: .. code-block:: ql @@ -161,8 +161,8 @@ Finally, on many Java projects there are methods that are invoked indirectly by ➤ `See this in the query console `__. This should give a further reduction in the number of results returned. -What next? ----------- +Further reading +--------------- - Find out how to query metadata and white space: :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index 360e3f9ab31..c3b33b98555 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -3,10 +3,10 @@ Analyzing data flow in Java You can use CodeQL to track the flow of data through a Java program to its use. -Overview --------- +About this article +------------------ -This topic describes how data flow analysis is implemented in the CodeQL libraries for Java and includes examples to help you write your own data flow queries. +This article describes how data flow analysis is implemented in the CodeQL libraries for Java and includes examples to help you write your own data flow queries. The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. @@ -19,7 +19,7 @@ Local data flow is data flow within a single method or callable. Local data flow Using local data flow ~~~~~~~~~~~~~~~~~~~~~ -The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). It is possible to map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: +The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). You can map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: .. code-block:: ql @@ -47,9 +47,9 @@ or using the predicates ``exprNode`` and ``parameterNode``: */ ParameterNode parameterNode(Parameter p) { ... } -The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or through the predefined recursive predicate ``localFlow``, which is equivalent to ``localFlowStep*``. +The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively by using the ``+`` and ``*`` operators, or by using the predefined recursive predicate ``localFlow``, which is equivalent to ``localFlowStep*``. -For example, finding flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -67,9 +67,9 @@ Local taint tracking extends local data flow by including non-value-preserving f If ``x`` is a tainted string then ``y`` is also tainted. -The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or through the predefined recursive predicate ``localTaint``, which is equivalent to ``localTaintStep*``. +The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively by using the ``+`` and ``*`` operators, or by using the predefined recursive predicate ``localTaint``, which is equivalent to ``localTaintStep*``. -For example, finding taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -78,7 +78,7 @@ For example, finding taint propagation from a parameter ``source`` to an express Examples ~~~~~~~~ -The following query finds the filename passed to ``new FileReader(..)``. +This query finds the filename passed to ``new FileReader(..)``. .. code-block:: ql @@ -90,7 +90,7 @@ The following query finds the filename passed to ``new FileReader(..)``. call.getCallee() = fileReader select call.getArgument(0) -Unfortunately, this will only give the expression in the argument, not the values which could be passed to it. So we use local data flow to find all expressions that flow into the argument: +Unfortunately, this only gives the expression in the argument, not the values which could be passed to it. So we use local data flow to find all expressions that flow into the argument: .. code-block:: ql @@ -104,7 +104,7 @@ Unfortunately, this will only give the expression in the argument, not the value DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0))) select src -Then we can make the source more specific, for example an access to a public parameter. The following query finds where a public parameter is passed to ``new FileReader(..)``: +Then we can make the source more specific, for example an access to a public parameter. This query finds where a public parameter is passed to ``new FileReader(..)``: .. code-block:: ql @@ -118,7 +118,7 @@ Then we can make the source more specific, for example an access to a public par DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(fc.getArgument(0))) select p -The following example finds calls to formatting functions where the format string is not hard-coded. +This query finds calls to formatting functions where the format string is not hard-coded. .. code-block:: ql @@ -150,7 +150,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ -The global data flow library is used by extending the class ``DataFlow::Configuration`` as follows: +You use the global data flow library by extending the class ``DataFlow::Configuration``: .. code-block:: ql @@ -168,7 +168,7 @@ The global data flow library is used by extending the class ``DataFlow::Configur } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: - ``isSource``—defines where data may flow from - ``isSink``—defines where data may flow to @@ -188,7 +188,7 @@ The data flow analysis is performed using the predicate ``hasFlow(DataFlow::Node Using global taint tracking ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Global taint tracking is to global data flow as local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class ``TaintTracking::Configuration`` as follows: +Global taint tracking is to global data flow as local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. You use the global taint tracking library by extending the class ``TaintTracking::Configuration``: .. code-block:: ql @@ -206,7 +206,7 @@ Global taint tracking is to global data flow as local taint tracking is to local } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: - ``isSource``—defines where taint may flow from - ``isSink``—defines where taint may flow to @@ -225,7 +225,7 @@ The data flow library contains some predefined flow sources. The class ``RemoteF Examples ~~~~~~~~ -The following example shows a taint-tracking configuration that uses remote user input as data sources. +This query shows a taint-tracking configuration that uses remote user input as data sources. .. code-block:: ql @@ -256,7 +256,7 @@ Exercise 4: Using the answers from 2 and 3, write a query which finds all global What next? ---------- -- Try the worked examples in the following topics: :doc:`Tutorial: Navigating the call graph ` and :doc:`Tutorial: Working with source locations `. +- Try the worked examples in these articles: :doc:`Tutorial: Navigating the call graph ` and :doc:`Tutorial: Working with source locations `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index 9fad2aa6faf..687f43213f1 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -3,12 +3,12 @@ Expressions and statements in Java You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow. -Overview --------- +About this article +------------------ -This tutorial develops a query for finding comparisons between integers and long integers in loops that may lead to non-termination due to overflow. +In this tutorial article you'll write a query for finding comparisons between integers and long integers in loops that may lead to non-termination due to overflow. -Specifically, consider the following code snippet: +To begin, consider this code snippet: .. code-block:: java @@ -26,12 +26,12 @@ If ``l`` is bigger than 2\ :sup:`31`\ - 1 (the largest positive value of type `` All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an "overflow"). For ``int``, this maximum value is 2\ :sup:`31`\ - 1. Type ``long`` can accommodate larger values up to a maximum of 2\ :sup:`63`\ - 1. In this example, this means that ``l`` can take on a value that is higher than the maximum for type ``int``; ``i`` will never be able to reach this value, instead overflowing and returning to a low value. -We will develop a query that finds code that looks like it might exhibit this kind of behavior. We will be using several of the standard library classes for representing statements and functions, a full list of which can be found in the :doc:`AST class reference `. +We're going to develop a query that finds code that looks like it might exhibit this kind of behavior. We'll be using several of the standard library classes for representing statements and functions, a full list of which can be found in the :doc:`AST class reference `. Initial query ------------- -We start out by writing a query that finds less-than expressions (CodeQL class ``LTExpr``) where the left operand is of type ``int`` and the right operand is of type ``long``: +We'll start by writing a query that finds less-than expressions (CodeQL class ``LTExpr``) where the left operand is of type ``int`` and the right operand is of type ``long``: .. code-block:: ql @@ -44,7 +44,7 @@ We start out by writing a query that finds less-than expressions (CodeQL class ` ➤ `See this in the query console `__. This query usually finds results on most projects. -Notice that we use the predicate ``getType`` (available on all subclasses of ``Expr``) to determine the type of the operands. Types, in turn, define the ``hasName`` predicate, which allows us to identify the primitive types ``int`` and ``long``. As it stands, this query finds *all* less-than expressions comparing ``int`` and ``long``, but in fact we are only interested in comparisons that are part of a loop condition. Also, we want to filter out comparisons where either operand is constant, since these are less likely to be real bugs. The revised query looks as follows: +Notice that we use the predicate ``getType`` (available on all subclasses of ``Expr``) to determine the type of the operands. Types, in turn, define the ``hasName`` predicate, which allows us to identify the primitive types ``int`` and ``long``. As it stands, this query finds *all* less-than expressions comparing ``int`` and ``long``, but in fact we are only interested in comparisons that are part of a loop condition. Also, we want to filter out comparisons where either operand is constant, since these are less likely to be real bugs. The revised query looks like this: .. code-block:: ql @@ -80,7 +80,7 @@ In order to compare the ranges of types, we define a predicate that returns the (pt.hasName("long") and result=64) } -We now want to generalize our query to apply to any comparison where the width of the type on the smaller end of the comparison is less than the width of the type on the greater end. Let us call such a comparison *overflow prone*, and introduce an abstract class to model it: +We now want to generalize our query to apply to any comparison where the width of the type on the smaller end of the comparison is less than the width of the type on the greater end. Let's call such a comparison *overflow prone*, and introduce an abstract class to model it: .. code-block:: ql @@ -122,8 +122,8 @@ Now we rewrite our query to make use of these new classes: ➤ `See the full query in the query console `__. -What next? ----------- +Further reading +--------------- - Have a look at some of the other tutorials: :doc:`Tutorial: Types and the class hierarchy `, :doc:`Tutorial: Navigating the call graph `, :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index b7529c1d2e7..c424b558224 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -3,8 +3,8 @@ CodeQL library for Java When you need to analyze a Java program, you can make use of the large collection of classes in the Java library for CodeQL. -Overview --------- +About the Java library +---------------------- There is an extensive library for analyzing CodeQL databases extracted from Java projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. @@ -42,7 +42,7 @@ These classes represent named program elements: packages (``Package``), compilat Their common superclass is ``Element``, which provides general member predicates for determining the name of a program element and checking whether two elements are nested inside each other. -It is often convenient to refer to an element that might either be a method or a constructor; the class ``Callable``, which is a common superclass of ``Method`` and ``Constructor``, can be used for this purpose. +It's often convenient to refer to an element that might either be a method or a constructor; the class ``Callable``, which is a common superclass of ``Method`` and ``Constructor``, can be used for this purpose. Types ~~~~~ @@ -68,9 +68,9 @@ For example, the following query finds all variables of type ``int`` in the prog pt.hasName("int") select v -➤ `See this in the query console `__. You are likely to get many results when you run this query because most projects contain many variables of type ``int``. +➤ `See this in the query console `__. You're likely to get many results when you run this query because most projects contain many variables of type ``int``. -Reference types can also be categorized according to their declaration scope: +Reference types are also categorized according to their declaration scope: - ``TopLevelType`` represents a reference type declared at the top-level of a compilation unit. - ``NestedType`` is a type declared inside another type. @@ -107,7 +107,7 @@ As an example, we can write a query that finds all nested classes that directly where nc.getASupertype() instanceof TypeObject select nc -➤ `See this in the query console `__. You are likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly. +➤ `See this in the query console `__. You're likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly. Generics ~~~~~~~~ @@ -196,7 +196,7 @@ The wildcards ``? extends Number`` and ``? super Float`` are represented by clas For dealing with generic methods, there are classes ``GenericMethod``, ``ParameterizedMethod`` and ``RawMethod``, which are entirely analogous to the like-named classes for representing generic types. -More information on working with types can be found in the :doc:`tutorial on types and the class hierarchy `. +For more information on working with types, see the :doc:`tutorial on types and the class hierarchy `. Variables ~~~~~~~~~ @@ -260,7 +260,7 @@ Finally, here is a query that finds method bodies: As these examples show, the parent node of an expression is not always an expression: it may also be a statement, for example, an ``IfStmt``. Similarly, the parent node of a statement is not always a statement: it may also be a method or a constructor. To capture this, the QL Java library provides two abstract class ``ExprParent`` and ``StmtParent``, the former representing any node that may be the parent node of an expression, and the latter any node that may be the parent node of a statement. - For more information on working with AST classes, see the :doc:`tutorial on expressions and statements `. +For more information on working with AST classes, see the :doc:`tutorial on expressions and statements `. Metadata -------- @@ -383,8 +383,8 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So For more information about callables and calls, see the :doc:`call graph tutorial `. -What next? ----------- +Further reading +--------------- - Experiment with the worked examples in the CodeQL for Java tutorial topics: :doc:`Types and the class hierarchy `, :doc:`Expressions and statements `, :doc:`Navigating the call graph `, :doc:`Annotations `, :doc:`Javadoc ` and :doc:`Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. diff --git a/docs/language/learn-ql/java/javadoc.rst b/docs/language/learn-ql/java/javadoc.rst index 03968a44230..efdd5ba8d1a 100644 --- a/docs/language/learn-ql/java/javadoc.rst +++ b/docs/language/learn-ql/java/javadoc.rst @@ -3,8 +3,8 @@ Javadoc You can use CodeQL to find errors in Javadoc comments in Java code. -Overview --------- +About analyzing Javadoc +----------------------- To access Javadoc associated with a program element, we use member predicate ``getDoc`` of class ``Element``, which returns a ``Documentable``. Class ``Documentable``, in turn, offers a member predicate ``getJavadoc`` to retrieve the Javadoc attached to the element in question, if any. @@ -51,9 +51,9 @@ The ``JavadocTag`` has several subclasses representing specific kinds of Javadoc Example: Finding spurious @param tags ------------------------------------- -As an example of using the CodeQL Javadoc API, let us write a query that finds ``@param`` tags that refer to a non-existent parameter. +As an example of using the CodeQL Javadoc API, let's write a query that finds ``@param`` tags that refer to a non-existent parameter. -For example, consider the following program: +For example, consider this program: .. code-block:: java @@ -78,7 +78,7 @@ To begin with, we write a query that finds all callables (that is, methods or co where c.getDoc().getJavadoc() = pt.getParent() select c, pt -It is now easy to add another conjunct to the ``where`` clause, restricting the query to ``@param`` tags that refer to a non-existent parameter: we simply need to require that no parameter of ``c`` has the name ``pt.getParamName()``. +It's now easy to add another conjunct to the ``where`` clause, restricting the query to ``@param`` tags that refer to a non-existent parameter: we simply need to require that no parameter of ``c`` has the name ``pt.getParamName()``. .. code-block:: ql @@ -94,7 +94,7 @@ Example: Finding spurious @throws tags A related, but somewhat more involved, problem is finding ``@throws`` tags that refer to an exception that the method in question cannot actually throw. -For example, consider the following Java program: +For example, consider this Java program: .. code-block:: java @@ -110,9 +110,9 @@ For example, consider the following Java program: } } -Notice that the Javadoc comment of ``A.foo`` documents two thrown exceptions: ``IOException`` and ``RuntimeException``. The former is clearly spurious: ``A.foo`` does not have a ``throws IOException`` clause, and thus cannot throw this kind of exception. On the other hand, ``RuntimeException`` is an unchecked exception, so it can be thrown even if there is no explicit ``throws`` clause listing it. Therefore, our query should flag the ``@throws`` tag for ``IOException``, but not the one for ``RuntimeException.`` +Notice that the Javadoc comment of ``A.foo`` documents two thrown exceptions: ``IOException`` and ``RuntimeException``. The former is clearly spurious: ``A.foo`` doesn't have a ``throws IOException`` clause, and therefore can't throw this kind of exception. On the other hand, ``RuntimeException`` is an unchecked exception, so it can be thrown even if there is no explicit ``throws`` clause listing it. So our query should flag the ``@throws`` tag for ``IOException``, but not the one for ``RuntimeException.`` -Recall from above that the CodeQL library represents ``@throws`` tags using class ``ThrowsTag``. This class does not provide a member predicate for determining the exception type that is being documented, so we first need to implement our own version. A simple version might look as follows: +Remember that the CodeQL library represents ``@throws`` tags using class ``ThrowsTag``. This class doesn't provide a member predicate for determining the exception type that is being documented, so we first need to implement our own version. A simple version might look like this: .. code-block:: ql @@ -120,7 +120,7 @@ Recall from above that the CodeQL library represents ``@throws`` tags using clas result.hasName(tt.getExceptionName()) } -Similarly, ``Callable`` does not come with a member predicate for querying all exceptions that the method or constructor may possibly throw. We can, however, implement this ourselves by using ``getAnException`` to find all ``throws`` clauses of the callable, and then use ``getType`` to resolve the corresponding exception types: +Similarly, ``Callable`` doesn't come with a member predicate for querying all exceptions that the method or constructor may possibly throw. We can, however, implement this ourselves by using ``getAnException`` to find all ``throws`` clauses of the callable, and then use ``getType`` to resolve the corresponding exception types: .. code-block:: ql @@ -133,7 +133,7 @@ Note the use of ``getASupertype*`` to find both exceptions declared in a ``throw Now we can write a query for finding all callables ``c`` and ``@throws`` tags ``tt`` such that: - ``tt`` belongs to a Javadoc comment attached to ``c``. -- ``c`` cannot throw the exception documented by ``tt``. +- ``c`` can't throw the exception documented by ``tt``. .. code-block:: ql @@ -154,10 +154,10 @@ Improvements Currently, there are two problems with this query: -#. ``getDocumentedException`` is too liberal: it will return *any* reference type with the right name, even if it is in a different package and not actually visible in the current compilation unit. -#. ``mayThrow`` is too restrictive: it does not account for unchecked exceptions, which do not need to be declared. +#. ``getDocumentedException`` is too liberal: it will return *any* reference type with the right name, even if it's in a different package and not actually visible in the current compilation unit. +#. ``mayThrow`` is too restrictive: it doesn't account for unchecked exceptions, which do not need to be declared. -To see why the former is a problem, consider the following program: +To see why the former is a problem, consider this program: .. code-block:: java @@ -168,9 +168,9 @@ To see why the former is a problem, consider the following program: void bar() throws IOException {} } -This program defines its own class ``IOException``, which is unrelated to the class ``java.io.IOException`` in the standard library: they are in different packages. Our ``getDocumentedException`` predicate does not check packages, however, so it will consider the ``@throws`` clause to refer to both ``IOException`` classes, and thus flag the ``@param`` tag as spurious, since ``B.bar`` cannot actually throw ``java.io.IOException``. +This program defines its own class ``IOException``, which is unrelated to the class ``java.io.IOException`` in the standard library: they are in different packages. Our ``getDocumentedException`` predicate doesn't check packages, however, so it will consider the ``@throws`` clause to refer to both ``IOException`` classes, and thus flag the ``@param`` tag as spurious, since ``B.bar`` can't actually throw ``java.io.IOException``. -As an example of the second problem, method ``A.foo`` from our previous example was annotated with a ``@throws RuntimeException`` tag. Our current version of ``mayThrow``, however, would think that ``A.foo`` cannot throw a ``RuntimeException``, and thus flag the tag as spurious. +As an example of the second problem, method ``A.foo`` from our previous example was annotated with a ``@throws RuntimeException`` tag. Our current version of ``mayThrow``, however, would think that ``A.foo`` can't throw a ``RuntimeException``, and thus flag the tag as spurious. We can make ``mayThrow`` less restrictive by introducing a new class to represent unchecked exceptions, which are just the subtypes of ``java.lang.RuntimeException`` and ``java.lang.Error``: @@ -198,7 +198,7 @@ Fixing ``getDocumentedException`` is more complicated, but we can easily cover t #. The ``@throws`` tag refers to a type in the same package. #. The ``@throws`` tag refers to a type that is imported by the current compilation unit. -The first case can be covered by changing ``getDocumentedException`` to use the qualified name of the ``@throws`` tag. To handle the second and the third case, we can introduce a new predicate ``visibleIn`` that checks whether a reference type is visible in a compilation unit, either by virtue of belonging to the same package or by being explicitly imported. We then rewrite ``getDocumentedException`` as follows: +The first case can be covered by changing ``getDocumentedException`` to use the qualified name of the ``@throws`` tag. To handle the second and the third case, we can introduce a new predicate ``visibleIn`` that checks whether a reference type is visible in a compilation unit, either by virtue of belonging to the same package or by being explicitly imported. We then rewrite ``getDocumentedException`` as: .. code-block:: ql @@ -216,10 +216,10 @@ The first case can be covered by changing ``getDocumentedException`` to use the ➤ `See this in the query console `__. This finds many fewer, more interesting results in the LGTM.com demo projects. -Currently, ``visibleIn`` only considers single-type imports, but it would be possible to extend it with support for other kinds of imports. +Currently, ``visibleIn`` only considers single-type imports, but you could extend it with support for other kinds of imports. -What next? ----------- +Further reading +--------------- - Find out how you can use the location API to define queries on whitespace: :doc:`Tutorial: Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. diff --git a/docs/language/learn-ql/java/source-locations.rst b/docs/language/learn-ql/java/source-locations.rst index ac9a9232568..491a8b218f5 100644 --- a/docs/language/learn-ql/java/source-locations.rst +++ b/docs/language/learn-ql/java/source-locations.rst @@ -3,10 +3,10 @@ Working with source locations You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. -Overview --------- +About source locations +---------------------- -Java offers a rich set of operators with complex precedence rules, which are sometimes confusing to developers. For instance, the class ``ByteBufferCache`` in the OpenJDK Java compiler (which is a member class of ``com.sun.tools.javac.util.BaseFileManager``) contains the following code for allocating a buffer: +Java offers a rich set of operators with complex precedence rules, which are sometimes confusing to developers. For instance, the class ``ByteBufferCache`` in the OpenJDK Java compiler (which is a member class of ``com.sun.tools.javac.util.BaseFileManager``) contains this code for allocating a buffer: .. code-block:: java @@ -16,14 +16,14 @@ Presumably, the author meant to allocate a buffer that is 1.5 times the size ind Note that the source layout gives a fairly clear indication of the intended meaning: there is more white space around ``+`` than around ``>>``, suggesting that the latter is meant to bind more tightly. -We will now develop a query that finds this kind of suspicious nesting, where the operator of the inner expression has more white space around it than the operator of the outer expression. This pattern may not necessarily indicate a bug, but at the very least it makes the code hard to read and prone to misinterpretation. +We're going to develop a query that finds this kind of suspicious nesting, where the operator of the inner expression has more white space around it than the operator of the outer expression. This pattern may not necessarily indicate a bug, but at the very least it makes the code hard to read and prone to misinterpretation. -White space is not directly represented in the CodeQL database, but we can deduce its presence from the location information associated with program elements and AST nodes. So we will start by providing an overview of source location management in the standard library for Java. +White space is not directly represented in the CodeQL database, but we can deduce its presence from the location information associated with program elements and AST nodes. So, before we write our query, we need an understanding of source location management in the standard library for Java. Location API ------------ -For every entity that has a representation in Java source code (including, in particular, program elements and AST nodes), the standard CodeQL library provides the following predicates for accessing source location information: +For every entity that has a representation in Java source code (including, in particular, program elements and AST nodes), the standard CodeQL library provides these predicates for accessing source location information: - ``getLocation`` returns a ``Location`` object describing the start and end position of the entity. - ``getFile`` returns a ``File`` object representing the file containing the entity. @@ -31,7 +31,7 @@ For every entity that has a representation in Java source code (including, in pa - ``getNumberOfCommentLines`` returns the number of comment lines. - ``getNumberOfLinesOfCode`` returns the number of non-comment lines. -For example, assume the following Java class is defined in compilation unit ``SayHello.java``: +For example, let's assume this Java class is defined in the compilation unit ``SayHello.java``: .. code-block:: java @@ -46,20 +46,20 @@ For example, assume the following Java class is defined in compilation unit ``Sa } } -Invoking ``getFile`` on the expression statement in the body of ``main`` will return a ``File`` object representing the file ``SayHello.java``. The statement spans four lines in total ``(getTotalNumberOfLines``), of which one is a comment line (``getNumberOfCommentLines``), while three lines contain code (``getNumberOfLinesOfCode``). +Invoking ``getFile`` on the expression statement in the body of ``main`` returns a ``File`` object representing the file ``SayHello.java``. The statement spans four lines in total ``(getTotalNumberOfLines``), of which one is a comment line (``getNumberOfCommentLines``), while three lines contain code (``getNumberOfLinesOfCode``). Class ``Location`` defines member predicates ``getStartLine``, ``getEndLine``, ``getStartColumn`` and ``getEndColumn`` to retrieve the line and column number an entity starts and ends at, respectively. Both lines and columns are counted starting from 1 (not 0), and the end position is inclusive, that is, it is the position of the last character belonging to the source code of the entity. In our example, the expression statement starts at line 5, column 3 (the first two characters on the line are tabs, which each count as one character), and it ends at line 8, column 4. -Class ``File`` defines the following member predicates: +Class ``File`` defines these member predicates: - ``getFullName`` returns the fully qualified name of the file. - ``getRelativePath`` returns the path of the file relative to the base directory of the source code. - ``getExtension`` returns the extension of the file. - ``getShortName`` returns the base name of the file, without its extension. -In our example, assume file ``A.java`` is located in directory ``/home/testuser/code/pkg``, where ``/home/testuser/code`` is the base directory of the program being analyzed. Then, a ``File`` object for ``A.java`` returns the following: +In our example, assume file ``A.java`` is located in directory ``/home/testuser/code/pkg``, where ``/home/testuser/code`` is the base directory of the program being analyzed. Then, a ``File`` object for ``A.java`` returns: - ``getFullName`` is ``/home/testuser/code/pkg/A.java``. - ``getRelativePath`` is ``pkg/A.java``. @@ -69,7 +69,7 @@ In our example, assume file ``A.java`` is located in directory ``/home/testuser/ Determining white space around an operator ------------------------------------------ -Let us start by considering how to write a predicate that computes the total amount of white space surrounding the operator of a given binary expression. If ``rcol`` is the start column of the expression's right operand and ``lcol`` is the end column of its left operand, then ``rcol - (lcol+1)`` gives us the total number of characters in between the two operands (note that we have to use ``lcol+1`` instead of ``lcol`` because end positions are inclusive). +Let's start by considering how to write a predicate that computes the total amount of white space surrounding the operator of a given binary expression. If ``rcol`` is the start column of the expression's right operand and ``lcol`` is the end column of its left operand, then ``rcol - (lcol+1)`` gives us the total number of characters in between the two operands (note that we have to use ``lcol+1`` instead of ``lcol`` because end positions are inclusive). This number includes the length of the operator itself, which we need to subtract out. For this, we can use predicate ``getOp``, which returns the operator string, surrounded by one white space on either side. Overall, the expression for computing the amount of white space around the operator of a binary expression ``expr`` is: @@ -90,12 +90,12 @@ Clearly, however, this only works if the entire expression is on a single line, ) } -Notice that we use an ``exists`` to introduce our temporary variables ``lcol`` and ``rcol``. The predicate could be written without them by just inlining ``lcol`` and ``rcol`` into their use, at some cost in readability. +Notice that we use an ``exists`` to introduce our temporary variables ``lcol`` and ``rcol``. You could write the predicate without them by just inlining ``lcol`` and ``rcol`` into their use, at some cost in readability. Find suspicious nesting ----------------------- -A first version of our query can now be written: +Here's a first version of our query: .. code-block:: ql @@ -125,7 +125,7 @@ If we run this initial query, we might notice some false positives arising from i< start + 100 -Note that our predicate ``operatorWS`` computes the **total** amount of white space around the operator, which, in this case, is one for the ``<`` and two for the ``+``. Ideally, we would like to exclude cases where the amount of white space before and after the operator are not the same. Currently, CodeQL databases do not record enough information to figure this out, but as an approximation we could require that the total number of white space characters is even: +Note that our predicate ``operatorWS`` computes the **total** amount of white space around the operator, which, in this case, is one for the ``<`` and two for the ``+``. Ideally, we would like to exclude cases where the amount of white space before and after the operator are not the same. Currently, CodeQL databases don't record enough information to figure this out, but as an approximation we could require that the total number of white space characters is even: .. code-block:: ql @@ -183,8 +183,8 @@ Notice that we again use ``getOp``, this time to determine whether two binary ex Whitespace suggests that the programmer meant to toggle ``i`` between zero and one, but in fact the expression is parsed as ``i + (1%2)``, which is the same as ``i + 1``, so ``i`` is simply incremented. -What next? ----------- +Further reading +--------------- - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index 2940da96cd6..35d4df4dfb3 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -3,8 +3,8 @@ Types in Java You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues. -Overview --------- +About working with Java types +----------------------------- The standard CodeQL library represents Java types by means of the ``Type`` class and its various subclasses. @@ -61,7 +61,7 @@ If the expression ``e`` happens to actually evaluate to a ``B[]`` array, on the Object[] o = new String[] { "Hello", "world" }; String[] s = (String[])o; -In this tutorial, we do not try to distinguish these two cases. Our query should simply look for cast expressions ``ce`` that cast from some type ``source`` to another type ``target``, such that: +In this tutorial, we don't try to distinguish these two cases. Our query should simply look for cast expressions ``ce`` that cast from some type ``source`` to another type ``target``, such that: - Both ``source`` and ``target`` are array types. - The element type of ``source`` is a transitive super type of the element type of ``target``. @@ -146,7 +146,7 @@ Using these new classes we can extend our query to exclude calls to ``toArray`` Example: Finding mismatched contains checks ------------------------------------------- -As another example, we develop a query that finds uses of ``Collection.contains`` where the type of the queried element is unrelated to the element type of the collection, thus guaranteeing that the test will always return ``false``. +We'll now develop a query that finds uses of ``Collection.contains`` where the type of the queried element is unrelated to the element type of the collection, which guarantees that the test will always return ``false``. For example, `Apache Zookeeper `__ used to have a snippet of code similar to the following in class ``QuorumPeerConfig``: @@ -274,7 +274,7 @@ Improvements For many programs, this query yields a large number of false positive results due to type variables and wild cards: if the collection element type is some type variable ``E`` and the argument type is ``String``, for example, CodeQL will consider that the two have no common subtype, and our query will flag the call. An easy way to exclude such false positive results is to simply require that neither ``collEltType`` nor ``argType`` are instances of ``TypeVariable``. -Another source of false positives is autoboxing of primitive types: if, for example, the collection's element type is ``Integer`` and the argument is of type ``int``, predicate ``haveCommonDescendant`` will fail, since ``int`` is not a ``RefType``. Thus, our query should check that ``collEltType`` is not the boxed type of ``argType``. +Another source of false positives is autoboxing of primitive types: if, for example, the collection's element type is ``Integer`` and the argument is of type ``int``, predicate ``haveCommonDescendant`` will fail, since ``int`` is not a ``RefType``. To account for this, our query should check that ``collEltType`` is not the boxed type of ``argType``. Finally, ``null`` is special because its type (known as ```` in the CodeQL library) is compatible with every reference type, so we should exclude it from consideration. @@ -296,8 +296,8 @@ Adding these three improvements, our final query becomes: ➤ `See the full query in the query console `__. -What next? ----------- +Further reading +--------------- - Take a look at some of the other tutorials: :doc:`Tutorial: Expressions and statements `, :doc:`Tutorial: Navigating the call graph `, :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. From f8c876176a046b7ea2657fe0585db1392b7f258c Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 19 Feb 2020 16:31:15 +0000 Subject: [PATCH 036/459] Apply suggestions from code review Many thanks for the review suggestions. Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/python/control-flow.rst | 8 ++++---- docs/language/learn-ql/python/functions.rst | 4 ++-- .../learn-ql/python/introduce-libraries-python.rst | 10 +++++----- docs/language/learn-ql/python/pointsto-type-infer.rst | 8 ++++---- .../learn-ql/python/statements-expressions.rst | 2 +- docs/language/learn-ql/python/taint-tracking.rst | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index 6fb7e8d919f..425f900dcd1 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -3,7 +3,7 @@ Analyzing control flow in Python You can write CodeQL queries to explore the control flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. -To analyze the control-flow graph of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. For more information, see `Control-flow graph `__ in Wikipedia. +To analyze the control-flow graph of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. For more information, see `Control-flow graph `__ on Wikipedia. The ``ControlFlowNode`` class ----------------------------- @@ -42,7 +42,7 @@ Example finding unreachable AST nodes where not exists(node.getAFlowNode()) select node -➤ `See this in the query console `__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements: +➤ `See this in the query console `__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements. Example finding unreachable statements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,12 +55,12 @@ Example finding unreachable statements where not exists(s.getAFlowNode()) select s -➤ `See this in the query console `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard query: unreachable code. For more information, see `Unreachable code `__ on LGTM.com. +➤ `See this in the query console `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard "Unreachable code" query. For more information, see `Unreachable code `__ on LGTM.com. The ``BasicBlock`` class ------------------------ -The ``BasicBlock`` class represents a basic block of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as, what can reach what, and what dominates what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. For more information, see `basic block `__ and `dominates `__ on Wikipedia. +The ``BasicBlock`` class represents a basic block of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as, what can reach what, and what dominates what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. For more information, see `Basic block `__ and `Dominator `__ on Wikipedia. Example finding mutually exclusive basic blocks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index a412b57e72a..2090372ac3c 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -3,7 +3,7 @@ Functions in Python Functions are key building blocks of Python code bases. You can find functions and identify calls to them using syntactic classes from the standard CodeQL library. -These examples use the standard CodeQL class `Function `__. For more information, see :doc:`Introducing the Python libraries `. +These examples use the standard CodeQL class `Function `__. For more information, see ":doc:`Introducing the Python libraries `." Finding all functions called "get..." ------------------------------------- @@ -57,7 +57,7 @@ We can modify the query further to include only methods whose body consists of a and count(f.getAStmt()) = 1 select f, "This function is (probably) a getter." -➤ `See this in the query console `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Tutorial: Statements and expressions `." +➤ `See this in the query console `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Expressions and statements in Python `." Finding a call to a specific function ------------------------------------- diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index d5c7ab77aab..3309487c191 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -22,12 +22,12 @@ The CodeQL library for Python incorporates a large number of classes. Each class Syntactic classes ----------------- -This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Abstract syntax tree `__ and `Symbolic information `__ in Wikipedia. +This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Abstract syntax tree `__ and `Symbolic information `__ on Wikipedia. Scope ^^^^^ -A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes (`Module `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``). +A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes `Module `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``. - ``Scope`` @@ -151,7 +151,7 @@ Both forms are equivalent. Using the positive expression, the whole query looks ➤ `See this in the query console `__. Many projects include pass-only ``except`` blocks. -Summary of syntactic classes +Summary ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The most commonly used standard classes in the syntactic part of the library are organized as follows: @@ -237,7 +237,7 @@ Other Control flow classes -------------------- -This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into basic blocks. For more information, see `basic blocks `__ in Wikipedia. +This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into basic blocks. For more information, see `Basic block `__ on Wikipedia. Example ^^^^^^^ @@ -332,7 +332,7 @@ Summary - `TaintKind `__ - `Configuration `__ -For more information about these classes, see ":doc:`Analyzing data flow and tracking tainted data in Python `". +For more information about these classes, see ":doc:`Analyzing data flow and tracking tainted data in Python `." Further reading diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index b64762c1d0d..6dfee9f4bbb 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -1,7 +1,7 @@ Pointer analysis and type inference in Python ============================================= -At run time, each Python expression has a value with an associated type. You can learn how an expression behaves at run time using type-inference classes from the standard CodeQL library. +At runtime, each Python expression has a value with an associated type. You can learn how an expression behaves at runtime using type-inference classes from the standard CodeQL library. This topic contains worked examples of how to write queries using the standard CodeQL library classes for Python type inference. @@ -25,7 +25,7 @@ Class hierarchy for ``Value``: Points-to analysis and type inference ------------------------------------- -Points-to analysis, sometimes known as pointer analysis, allows us to determine which objects an expression may "point to" at runtime. Type inference allows us to infer what the types (classes) of an expression may be at runtime. For more information, see `pointer analysis `__ and `Type inference `__ on Wikipedia. +Points-to analysis, sometimes known as pointer analysis, allows us to determine which objects an expression may "point to" at runtime. Type inference allows us to infer what the types (classes) of an expression may be at runtime. For more information, see `Pointer analysis `__ and `Type inference `__ on Wikipedia. The predicate ``ControlFlowNode.pointsTo(...)`` shows which object a control flow node may "point to" at runtime. @@ -124,7 +124,7 @@ Combining the parts of the query we get this: ) select t, ex1, ex2 -➤ `See this in the query console `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard query: Unreachable 'except' block. For more information, see `Unreachable 'except' block `__ on LGTM.com. +➤ `See this in the query console `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard "Unreachable 'except' block" query. For more information, see `Unreachable 'except' block `__ on LGTM.com. .. pull-quote:: @@ -184,7 +184,7 @@ The ``Value`` class has a method ``getACall()`` which allows us to find calls to If we wish to restrict the callables to actual functions we can use the ``FunctionValue`` class, which is a subclass of ``Value`` and corresponds to function objects in Python, in much the same way as the ``ClassValue`` class corresponds to class objects in Python. -Returning to an example from ":doc:`Tutorial: Functions `," we wish to find calls to the ``eval`` function. +Returning to an example from ":doc:`Functions in Python `," we wish to find calls to the ``eval`` function. The original query looked this: diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 2b857f4f9a2..209d22ae3d1 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -197,7 +197,7 @@ The short version is usually used as this is easier to read. Example finding Java-style getters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Returning to the example from ":doc:`Tutorial: Functions `," the query identified all methods with a single line of code and a name starting with ``get``. +Returning to the example from ":doc:`Functions in Python `," the query identified all methods with a single line of code and a name starting with ``get``. .. code-block:: ql diff --git a/docs/language/learn-ql/python/taint-tracking.rst b/docs/language/learn-ql/python/taint-tracking.rst index ff9eff4ed6f..bfdae7aa4eb 100644 --- a/docs/language/learn-ql/python/taint-tracking.rst +++ b/docs/language/learn-ql/python/taint-tracking.rst @@ -1,7 +1,7 @@ Analyzing data flow and tracking tainted data in Python ======================================================= -You can use CodeQL to track the flow of data through a Python program to its use. Tracking user-controlled, or tainted, data is a key technique for security researchers. +You can use CodeQL to track the flow of data through a Python program. Tracking user-controlled, or tainted, data is a key technique for security researchers. About data flow and taint tracking ---------------------------------- From 552d2edb5b128a309aa24cf7faa318c5504c695e Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 19 Feb 2020 16:35:59 +0000 Subject: [PATCH 037/459] Correction one more mention of tutorials --- docs/language/learn-ql/python/control-flow.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index 425f900dcd1..736bb89f08b 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -109,7 +109,7 @@ Example finding mutually exclusive blocks within the same function ) select b1, b2 -➤ `See this in the query console `__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis which is covered in the next tutorial. +➤ `See this in the query console `__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis. For more information, see :doc:`Analyzing data flow and tracking tainted data in Python `. Further reading --------------- From 1da1d921707694535d9847f812381b3d7e25af74 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 19 Feb 2020 16:39:29 +0000 Subject: [PATCH 038/459] Update intro for library overview topic Based on suggestions from James and Shati --- .../language/learn-ql/python/introduce-libraries-python.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 3309487c191..fa0a0ac7bcb 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -1,12 +1,14 @@ CodeQL library for Python ========================= -Overview of the extensive library you use to analyze databases generated from Python code bases. This library uses classes with abstractions and predicates to present the data in an object-oriented form. This abstraction makes it easier for you to write queries. +This is an overview of the extensive library you use to analyze databases generated from Python code bases. Using this library makes it easier for you to write queries. About the CodeQL library for Python ----------------------------------- -The CodeQL library for each programming language is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: +The CodeQL library for each programming language uses classes with abstractions and predicates to present data in an object-oriented form. This abstraction makes it easier for you to write queries. + +Each CodeQL library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: .. code-block:: ql From eb2fdda6aa1e72cbb9df116cc779fb93ed185dad Mon Sep 17 00:00:00 2001 From: Alistair Christie Date: Wed, 19 Feb 2020 16:50:33 +0000 Subject: [PATCH 039/459] C# pre-migration changes: titles & intros --- docs/language/learn-ql/csharp/dataflow.rst | 112 +++++++------- .../csharp/introduce-libraries-csharp.rst | 142 +++++++++--------- .../learn-ql/csharp/ql-for-csharp.rst | 2 + 3 files changed, 131 insertions(+), 125 deletions(-) diff --git a/docs/language/learn-ql/csharp/dataflow.rst b/docs/language/learn-ql/csharp/dataflow.rst index 3b9bb69d7da..b60ab2e245d 100644 --- a/docs/language/learn-ql/csharp/dataflow.rst +++ b/docs/language/learn-ql/csharp/dataflow.rst @@ -1,11 +1,13 @@ Analyzing data flow in C# ========================= -Overview --------- +You can use CodeQL to track the flow of data through a C# program to its use. -This topic describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. +About this article +------------------ + +This article describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries. +The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. @@ -17,7 +19,7 @@ Local data flow is data flow within a single method or callable. Local data flow Using local data flow ~~~~~~~~~~~~~~~~~~~~~ -The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). It is possible to map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: +The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). You can map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: .. code-block:: ql @@ -45,9 +47,9 @@ or using the predicates ``exprNode`` and ``parameterNode``: */ ParameterNode parameterNode(Parameter p) { ... } -The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or it is possible to use the predefined recursive predicate ``localFlow``. +The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively, by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localFlow``. -For example, finding flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -65,9 +67,9 @@ Local taint tracking extends local data flow by including non-value-preserving f If ``x`` is a tainted string then ``y`` is also tainted. -The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or it is possible to use the predefined recursive predicate ``localTaint``. +The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively, by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localTaint``. -For example, finding taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -76,7 +78,7 @@ For example, finding taint propagation from a parameter ``source`` to an express Examples ~~~~~~~~ -The following query finds the filename passed to ``System.IO.File.Open``: +This query finds the filename passed to ``System.IO.File.Open``: .. code-block:: ql @@ -99,7 +101,7 @@ Unfortunately this will only give the expression in the argument, not the values and DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0))) select src -Then we can make the source more specific, for example an access to a public parameter. The following query finds where a public parameter is used to open a file: +Then we can make the source more specific, for example an access to a public parameter. This query finds instances of a public parameter being used to open a file: .. code-block:: ql @@ -112,7 +114,7 @@ Then we can make the source more specific, for example an access to a public par and call.getEnclosingCallable().(Member).isPublic() select p, "Opening a file from a public method." -The following example finds calls to ``String.Format`` where the format string isn't hard-coded: +This query finds calls to ``String.Format`` where the format string isn't hard-coded: .. code-block:: ql @@ -139,7 +141,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ -The global data flow library is used by extending the class ``DataFlow::Configuration`` as follows: +The global data flow library is used by extending the class ``DataFlow::Configuration``: .. code-block:: ql @@ -157,12 +159,12 @@ The global data flow library is used by extending the class ``DataFlow::Configur } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: -- ``isSource`` - defines where data may flow from -- ``isSink`` - defines where data may flow to -- ``isBarrier`` - optionally, restricts the data flow -- ``isAdditionalFlowStep`` - optionally, adds additional flow steps +- ``isSource`` - defines where data may flow from. +- ``isSink`` - defines where data may flow to. +- ``isBarrier`` - optionally, restricts the data flow. +- ``isAdditionalFlowStep`` - optionally, adds additional flow steps. The characteristic predicate (``MyDataFlowConfiguration()``) defines the name of the configuration, so ``"..."`` must be replaced with a unique name. @@ -177,7 +179,7 @@ The data flow analysis is performed using the predicate ``hasFlow(DataFlow::Node Using global taint tracking ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Global taint tracking is to global data flow what local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class ``TaintTracking::Configuration`` as follows: +Global taint tracking is to global data flow what local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class ``TaintTracking::Configuration``: .. code-block:: ql @@ -195,12 +197,12 @@ Global taint tracking is to global data flow what local taint tracking is to loc } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: -- ``isSource`` - defines where taint may flow from -- ``isSink`` - defines where taint may flow to -- ``isSanitizer`` - optionally, restricts the taint flow -- ``isAdditionalTaintStep`` - optionally, adds additional taint steps +- ``isSource`` - defines where taint may flow from. +- ``isSink`` - defines where taint may flow to. +- ``isSanitizer`` - optionally, restricts the taint flow. +- ``isAdditionalTaintStep`` - optionally, adds additional taint steps. Similar to global data flow, the characteristic predicate (``MyTaintTrackingConfiguration()``) defines the unique name of the configuration and the taint analysis is performed using the predicate ``hasFlow(DataFlow::Node source, DataFlow::Node sink)``. @@ -214,7 +216,7 @@ The class ``RemoteSourceFlow`` (defined in module ``semmle.code.csharp.dataflow. Example ~~~~~~~ -The following example shows a data flow configuration that uses all public API parameters as data sources. +This query shows a data flow configuration that uses all public API parameters as data sources: .. code-block:: ql @@ -236,30 +238,30 @@ The following example shows a data flow configuration that uses all public API p Class hierarchy ~~~~~~~~~~~~~~~ -- ``DataFlow::Configuration`` - base class for custom global data flow analysis -- ``DataFlow::Node`` - an element behaving as a data flow node +- ``DataFlow::Configuration`` - base class for custom global data flow analysis. +- ``DataFlow::Node`` - an element behaving as a data flow node. - - ``DataFlow::ExprNode`` - an expression behaving as a data flow node - - ``DataFlow::ParameterNode`` - a parameter data flow node representing the value of a parameter at function entry + - ``DataFlow::ExprNode`` - an expression behaving as a data flow node. + - ``DataFlow::ParameterNode`` - a parameter data flow node representing the value of a parameter at function entry. - - ``PublicCallableParameter`` - a parameter to a public method/callable in a public class + - ``PublicCallableParameter`` - a parameter to a public method/callable in a public class. - - ``RemoteSourceFlow`` - data flow from network/remote input + - ``RemoteSourceFlow`` - data flow from network/remote input. - - ``AspNetRemoteFlowSource`` - data flow from remote ASP.NET user input + - ``AspNetRemoteFlowSource`` - data flow from remote ASP.NET user input. - - ``AspNetQueryStringRemoteFlowSource`` - data flow from ``System.Web.HttpRequest`` - - ``AspNetUserInputRemoveFlowSource`` - data flow from ``System.Web.IO.WebControls.TextBox`` + - ``AspNetQueryStringRemoteFlowSource`` - data flow from ``System.Web.HttpRequest``. + - ``AspNetUserInputRemoveFlowSource`` - data flow from ``System.Web.IO.WebControls.TextBox``. - - ``WcfRemoteFlowSource`` - data flow from a WCF web service - - ``AspNetServiceRemoteFlowSource`` - data flow from an ASP.NET web service + - ``WcfRemoteFlowSource`` - data flow from a WCF web service. + - ``AspNetServiceRemoteFlowSource`` - data flow from an ASP.NET web service. -- ``TaintTracking::Configuration`` - base class for custom global taint tracking analysis +- ``TaintTracking::Configuration`` - base class for custom global taint tracking analysis. Examples ~~~~~~~~ -The following data flow configuration tracks data flow from environment variables to opening files: +This data flow configuration tracks data flow from environment variables to opening files: .. code-block:: ql @@ -300,7 +302,7 @@ Exercise 4: Using the answers from 2 and 3, write a query to find all global dat Extending library data flow --------------------------- -*Library* data flow defines how data flows through libraries where the source code is not available, such as the .NET Framework, third-party libraries or proprietary libraries. +Library data flow defines how data flows through libraries where the source code is not available, such as the .NET Framework, third-party libraries or proprietary libraries. To define new library data flow, extend the class ``LibraryTypeDataFlow`` from the module ``semmle.code.csharp.dataflow.LibraryTypeDataFlow``. Override the predicate ``callableFlow`` to define how data flows through the methods in the class. ``callableFlow`` has the signature @@ -308,9 +310,9 @@ To define new library data flow, extend the class ``LibraryTypeDataFlow`` from t predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable callable, boolean preservesValue) -- ``callable`` - the ``Callable`` (such as a method, constructor, property getter or setter) performing the data flow -- ``source`` - the data flow input -- ``sink`` - the data flow output +- ``callable`` - the ``Callable`` (such as a method, constructor, property getter or setter) performing the data flow. +- ``source`` - the data flow input. +- ``sink`` - the data flow output. - ``preservesValue`` - whether the flow step preserves the value, for example if ``x`` is a string then ``x.ToString()`` preserves the value where as ``x.ToLower()`` does not. Class hierarchy @@ -318,24 +320,24 @@ Class hierarchy - ``Callable`` - a callable (methods, accessors, constructors etc.) - - ``SourceDeclarationCallable`` - an unconstructed callable + - ``SourceDeclarationCallable`` - an unconstructed callable. -- ``CallableFlowSource`` - the input of data flow into the callable +- ``CallableFlowSource`` - the input of data flow into the callable. - - ``CallableFlowSourceQualifier`` - the data flow comes from the object itself - - ``CallableFlowSourceArg`` - the data flow comes from an argument to the call + - ``CallableFlowSourceQualifier`` - the data flow comes from the object itself. + - ``CallableFlowSourceArg`` - the data flow comes from an argument to the call. -- ``CallableFlowSink`` - the output of data flow from the callable +- ``CallableFlowSink`` - the output of data flow from the callable. - - ``CallableFlowSinkQualifier`` - the output is to the object itself - - ``CallableFlowSinkReturn`` - the output is returned from the call - - ``CallableFlowSinkArg`` - the output is an argument - - ``CallableFlowSinkDelegateArg`` - the output flows through a delegate argument (for example, LINQ) + - ``CallableFlowSinkQualifier`` - the output is to the object itself. + - ``CallableFlowSinkReturn`` - the output is returned from the call. + - ``CallableFlowSinkArg`` - the output is an argument. + - ``CallableFlowSinkDelegateArg`` - the output flows through a delegate argument (for example, LINQ). Example ~~~~~~~ -The following example is adapted from ``LibraryTypeDataFlow.qll``. It declares data flow through the class ``System.Uri``, including the constructor, the ``ToString`` method, and the properties ``Query``, ``OriginalString``, and ``PathAndQuery``. +This example is adapted from ``LibraryTypeDataFlow.qll``. It declares data flow through the class ``System.Uri``, including the constructor, the ``ToString`` method, and the properties ``Query``, ``OriginalString``, and ``PathAndQuery``. .. code-block:: ql @@ -489,7 +491,7 @@ Exercise 4 Exercise 5 ~~~~~~~~~~ -All properties can flow data. We can declare this as follows: +All properties can flow data: .. code-block:: ql @@ -545,8 +547,8 @@ This can be adapted from the ``SystemUriFlow`` class: } } -What next? ----------- +Further reading +--------------- - Learn about the standard libraries used to write queries for C# in :doc:`Introducing the C# libraries `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index 32a782d5034..c52695f92d3 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1,8 +1,10 @@ -Introducing the CodeQL libraries for C# -======================================= +CodeQL library for C# +===================== -Overview --------- +When you need to analyze a C# program, you can make use of the large collection of classes in the C# library for CodeQL. + +About the C# library +-------------------- There is an extensive library for analyzing CodeQL databases extracted from C# projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``csharp.qll`` imports all the core C# library modules, so you can include the complete library by beginning your query with: @@ -10,9 +12,9 @@ There is an extensive library for analyzing CodeQL databases extracted from C# p import csharp -Since this is required for all C# queries, it is omitted from code snippets below. +Since this is required for all C# queries, it's omitted from code snippets below. -The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. See :doc:`CodeQL for C# ` for information about these additional libraries. +The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. For information about these additional libraries, see :doc:`CodeQL for C# `. Class hierarchies ~~~~~~~~~~~~~~~~~ @@ -42,7 +44,7 @@ Each section contains a class hierarchy, showing the inheritance structure betwe - ``AddExpr``, ``SubExpr``, ``MulExpr``, ``DivExpr``, ``RemExpr`` -This means that the class ``AddExpr`` extends class ``BinaryArithmeticOperation``, which in turn extends class ``ArithmeticOperation`` and so on. If you want to query any arithmetic operation, then use the class ``ArithmeticOperation``, but if you specifically want to limit the query to addition operations, then use the class ``AddExpr``. +This means that the class ``AddExpr`` extends class ``BinaryArithmeticOperation``, which in turn extends class ``ArithmeticOperation`` and so on. If you want to query any arithmetic operation, use the class ``ArithmeticOperation``, but if you specifically want to limit the query to addition operations, use the class ``AddExpr``. Classes can also be considered to be *sets*, and the ``extends`` relation between classes defines a subset. Every member of class ``AddExpr`` is also in the class ``BinaryArithmeticOperation``. In general, classes overlap and an entity can be a member of several classes. @@ -50,14 +52,14 @@ This overview omits some of the less important or intermediate classes from the Each class has predicates, which are logical propositions about that class. They also define navigable relationships between classes. Predicates are inherited, so for example the ``AddExpr`` class inherits the predicates ``getLeftOperand()`` and ``getRightOperand()`` from ``BinaryArithmeticOperation``, and ``getType()`` from class ``Expr``. This is similar to how methods are inherited in object-oriented programming languages. -In this overview, we present the most common and useful predicates. Consult the `reference `__, the CodeQL source code, and autocomplete in the editor for the complete list of predicates available on each class. +In this overview, we present the most common and useful predicates. For the complete list of predicates available on each class, you can look in the CodeQL source code, use autocomplete in the editor, or see the `C# reference `__. Exercises ~~~~~~~~~ Each section in this topic contains exercises to check your understanding. -Exercise 1: Simplify the following query: +Exercise 1: Simplify this query: .. code-block:: ql @@ -84,11 +86,11 @@ Class hierarchy Predicates ~~~~~~~~~~ -- ``getName()`` - gets the full path of the file (for example, ``C:\Temp\test.cs``) -- ``getNumberOfLines()`` - gets the number of lines (for source files only) -- ``getShortName()`` - gets the name of the file without the extension (for example, ``test``) -- ``getBaseName()`` - gets the name and extension of the file (for example, ``test.cs``) -- ``getParent()`` - gets the parent directory +- ``getName()`` - gets the full path of the file (for example, ``C:\Temp\test.cs``). +- ``getNumberOfLines()`` - gets the number of lines (for source files only). +- ``getShortName()`` - gets the name of the file without the extension (for example, ``test``). +- ``getBaseName()`` - gets the name and extension of the file (for example, ``test.cs``). +- ``getParent()`` - gets the parent directory. Examples ~~~~~~~~ @@ -116,7 +118,7 @@ Exercise 2: Write a query to find the source file with the largest number of lin Elements -------- -The class `Element `__ is the base class for all parts of a C# program, and it is the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class. +The class `Element `__ is the base class for all parts of a C# program, and it's the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class. ``Element`` forms a hierarchical structure of the program, which can be navigated using the ``getParent()`` and ``getChild()`` predicates. This is much like an abstract syntax tree, and also applies to elements in assemblies. @@ -125,10 +127,10 @@ Predicates The ``Element`` class provides common functionality for all program elements, including: -- ``getLocation()`` - gets the text span in the source code -- ``getFile()`` - gets the ``File`` containing the ``Element`` -- ``getParent()`` - gets the parent ``Element``, if any -- ``getAChild()`` - gets a child ``Element`` of this element, if any +- ``getLocation()`` - gets the text span in the source code. +- ``getFile()`` - gets the ``File`` containing the ``Element``. +- ``getParent()`` - gets the parent ``Element``, if any. +- ``getAChild()`` - gets a child ``Element`` of this element, if any. Examples ~~~~~~~~ @@ -163,11 +165,11 @@ Predicates Some predicates of ``Location`` include: -- ``getFile()`` - gets the ``File`` -- ``getStartLine()`` - gets the first line of the text -- ``getEndLine()`` - gets the last line of the text -- ``getStartColumn()`` - gets the column of the start of the text -- ``getEndColumn()`` - gets the column of the end of the text +- ``getFile()`` - gets the ``File``. +- ``getStartLine()`` - gets the first line of the text. +- ``getEndLine()`` - gets the last line of the text. +- ``getStartColumn()`` - gets the column of the start of the text. +- ``getEndColumn()`` - gets the column of the end of the text. Examples ~~~~~~~~ @@ -213,10 +215,10 @@ Predicates Useful member predicates on ``Declaration`` include: -- ``getDeclaringType()`` - gets the type containing the declaration, if any -- ``getName()``/``hasName(string)`` - gets the name of the declared entity -- ``isSourceDeclaration()`` - whether the declaration is source code and is not a constructed type/method -- ``getSourceDeclaration()`` - gets the original (unconstructed) declaration +- ``getDeclaringType()`` - gets the type containing the declaration, if any. +- ``getName()``/``hasName(string)`` - gets the name of the declared entity. +- ``isSourceDeclaration()`` - whether the declaration is source code and is not a constructed type/method. +- ``getSourceDeclaration()`` - gets the original (unconstructed) declaration. Examples ~~~~~~~~ @@ -262,10 +264,10 @@ Predicates Some common predicates on ``Variable`` are: -- ``getType()`` - gets the ``Type`` of this variable -- ``getAnAccess()`` - gets an expression that accesses (reads or writes) this variable, if any -- ``getAnAssignedValue()`` - gets an expression that is assigned to this variable, if any -- ``getInitializer()`` - gets the expression used to initialize the variable, if any +- ``getType()`` - gets the ``Type`` of this variable. +- ``getAnAccess()`` - gets an expression that accesses (reads or writes) this variable, if any. +- ``getAnAssignedValue()`` - gets an expression that is assigned to this variable, if any. +- ``getInitializer()`` - gets the expression used to initialize the variable, if any. Examples ~~~~~~~~ @@ -309,7 +311,7 @@ Class hierarchy - ``VoidType`` - ``void`` - ``PointerType`` - a pointer type -The ``ValueType`` class extends further as follows: +The ``ValueType`` class extends further: - ``ValueType`` - a value type @@ -345,7 +347,7 @@ The ``ValueType`` class extends further as follows: - ``NullableType`` - ``ArrayType`` -The ``RefType`` class extends further as follows: +The ``RefType`` class extends further: - ``RefType`` @@ -369,19 +371,19 @@ Predicates Useful members of ``ValueOrRefType`` include: -- ``getQualifiedName()/hasQualifiedName(string)`` - gets the qualified name of the type (for example, ``"System.String"``) -- ``getABaseInterface()`` - gets an immediate interface of this type, if any -- ``getABaseType()`` - gets an immediate base class or interface of this type, if any -- ``getBaseClass()`` - gets the immediate base class of this type, if any -- ``getASubType()`` - gets an immediate subtype, a type which directly inherits from this type, if any -- ``getAMember()`` - gets any member (field/method/property etc), if any -- ``getAMethod()`` - gets a method, if any -- ``getAProperty()`` - gets a property, if any -- ``getAnIndexer()`` - gets an indexer, if any -- ``getAnEvent()`` - gets an event, if any -- ``getAnOperator()`` - gets an operator, if any -- ``getANestedType()`` - gets a nested type -- ``getNamespace()`` - gets the enclosing namespace +- ``getQualifiedName()/hasQualifiedName(string)`` - gets the qualified name of the type (for example, ``"System.String"``). +- ``getABaseInterface()`` - gets an immediate interface of this type, if any. +- ``getABaseType()`` - gets an immediate base class or interface of this type, if any. +- ``getBaseClass()`` - gets the immediate base class of this type, if any. +- ``getASubType()`` - gets an immediate subtype, a type which directly inherits from this type, if any. +- ``getAMember()`` - gets any member (field/method/property etc), if any. +- ``getAMethod()`` - gets a method, if any. +- ``getAProperty()`` - gets a property, if any. +- ``getAnIndexer()`` - gets an indexer, if any. +- ``getAnEvent()`` - gets an event, if any. +- ``getAnOperator()`` - gets an operator, if any. +- ``getANestedType()`` - gets a nested type. +- ``getNamespace()`` - gets the enclosing namespace. Examples ~~~~~~~~ @@ -492,12 +494,12 @@ Predicates Here are a few useful predicates on the ``Callable`` class: -- ``getParameter(int)``/``getAParameter()`` - gets a parameter -- ``calls(Callable)`` - whether there's a direct call from one callable to another -- ``getReturnType()`` - gets the return type -- ``getBody()``/``getExpressionBody()`` - gets the body of the callable +- ``getParameter(int)``/``getAParameter()`` - gets a parameter. +- ``calls(Callable)`` - whether there's a direct call from one callable to another. +- ``getReturnType()`` - gets the return type. +- ``getBody()``/``getExpressionBody()`` - gets the body of the callable. -Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declaration``, such as +Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declaration``, such as: - ``getName()``/``hasName(string)`` - ``getSourceDeclaration()`` @@ -506,10 +508,10 @@ Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declar Methods have additional predicates, including: -- ``getAnOverridee()`` - gets a method that is immediately overridden by this method -- ``getAnOverrider()`` - gets a method that immediately overrides this method -- ``getAnImplementee()`` - gets an interface method that is immediately implemented by this method -- ``getAnImplementor()`` - gets a method that immediately implements this interface method +- ``getAnOverridee()`` - gets a method that is immediately overridden by this method. +- ``getAnOverrider()`` - gets a method that immediately overrides this method. +- ``getAnImplementee()`` - gets an interface method that is immediately implemented by this method. +- ``getAnImplementor()`` - gets a method that immediately implements this interface method. Examples ~~~~~~~~ @@ -665,7 +667,7 @@ Find an ``if`` statement with a constant condition: where ifStmt.getCondition().hasValue() select ifStmt, "This 'if' statement is constant." -Find an ``if`` statement with an empty "then" clause: +Find an ``if`` statement with an empty "then" block: .. code-block:: ql @@ -680,7 +682,7 @@ Exercises Exercise 6: Write a query to list all empty methods. (`Answer <#exercise-6>`__) -Exercise 7: Modify the last example to also detect empty statements (``;``) in the then block. (`Answer <#exercise-7>`__) +Exercise 7: Modify the last example to also detect empty statements (``;``) in the "then" block. (`Answer <#exercise-7>`__) Exercise 8: Modify the last example to exclude chains of ``if`` statements, where the ``else`` part is another ``if`` statement. (`Answer <#exercise-8>`__) @@ -874,13 +876,13 @@ Predicates Useful predicates on ``Expr`` include: -- ``getType()`` - gets the ``Type`` of the expression -- ``getValue()`` - gets the compile-time constant, if any -- ``hasValue()`` - whether the expression has a compile-time constant -- ``getEnclosingStmt()`` - gets the statement containing the expression, if any -- ``getEnclosingCallable()`` - gets the callable containing the expression, if any -- ``stripCasts()`` - remove all explicit or implicit casts -- ``isImplicit()`` - whether the expression was implicit, such as an implicit ``this`` qualifier (``ThisAccess``) +- ``getType()`` - gets the ``Type`` of the expression. +- ``getValue()`` - gets the compile-time constant, if any. +- ``hasValue()`` - whether the expression has a compile-time constant. +- ``getEnclosingStmt()`` - gets the statement containing the expression, if any. +- ``getEnclosingCallable()`` - gets the callable containing the expression, if any. +- ``stripCasts()`` - remove all explicit or implicit casts. +- ``isImplicit()`` - whether the expression was implicit, such as an implicit ``this`` qualifier (``ThisAccess``). Examples ~~~~~~~~ @@ -922,7 +924,7 @@ Attributes C# attributes are represented by the class `Attribute `__. They can be present on many C# elements, such as classes, methods, fields, and parameters. The database contains attributes from the source code and all assembly references. -The attribute of any ``Element`` can be obtained via ``getAnAttribute()``, whereas if you have an attribute, you can find its element via ``getTarget()``. The following two query fragments are identical: +The attribute of any ``Element`` can be obtained via ``getAnAttribute()``, whereas if you have an attribute, you can find its element via ``getTarget()``. These two query fragments are identical: .. code-block:: ql @@ -939,8 +941,8 @@ Class hierarchy Predicates ~~~~~~~~~~ -- ``getTarget()`` - gets the ``Element`` to which this attribute applies -- ``getArgument(int)`` - gets the given argument of the attribute +- ``getTarget()`` - gets the ``Element`` to which this attribute applies. +- ``getArgument(int)`` - gets the given argument of the attribute. - ``getType()`` - gets the type of this attribute. Note that the class name must end in ``"Attribute"``. Examples @@ -1117,8 +1119,8 @@ Here is the fixed version: else reason = "(not given)" select e, "This is obsolete because " + reason -What next? ----------- +Further reading +--------------- - Visit :doc:`Tutorial: Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/csharp/ql-for-csharp.rst b/docs/language/learn-ql/csharp/ql-for-csharp.rst index bc5cc9e9959..67bec1ff60b 100644 --- a/docs/language/learn-ql/csharp/ql-for-csharp.rst +++ b/docs/language/learn-ql/csharp/ql-for-csharp.rst @@ -1,6 +1,8 @@ CodeQL for C# ============= +You can use CodeQL to explore C# programs and quickly find variants of security vulnerabilities and bugs. + .. toctree:: :glob: :hidden: From 96f37c910b9530b28c25fddc3c29c12b18f8623b Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Thu, 20 Feb 2020 12:32:18 +0000 Subject: [PATCH 040/459] Apply suggestions from code review --- docs/language/learn-ql/python/functions.rst | 2 +- docs/language/learn-ql/python/introduce-libraries-python.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index 2090372ac3c..a58f7ef889a 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -1,7 +1,7 @@ Functions in Python =================== -Functions are key building blocks of Python code bases. You can find functions and identify calls to them using syntactic classes from the standard CodeQL library. +Functions are key building blocks of Python code bases. You can use syntactic classes from the standard CodeQL library to find functions and identify calls to them. These examples use the standard CodeQL class `Function `__. For more information, see ":doc:`Introducing the Python libraries `." diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index fa0a0ac7bcb..44818219bb6 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -6,7 +6,7 @@ This is an overview of the extensive library you use to analyze databases genera About the CodeQL library for Python ----------------------------------- -The CodeQL library for each programming language uses classes with abstractions and predicates to present data in an object-oriented form. This abstraction makes it easier for you to write queries. +The CodeQL library for each programming language uses classes with abstractions and predicates to present data in an object-oriented form. Each CodeQL library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: From 6da729c6a6a422f8d451c559719db405cc234355 Mon Sep 17 00:00:00 2001 From: mchammer01 <42146119+mchammer01@users.noreply.github.com> Date: Fri, 21 Feb 2020 11:50:37 +0000 Subject: [PATCH 041/459] pre-migration tasks: replace titles --- docs/language/learn-ql/javascript/ast-class-reference.rst | 4 ++-- docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst | 4 ++-- docs/language/learn-ql/javascript/flow-labels.rst | 4 ++-- docs/language/learn-ql/javascript/introduce-libraries-js.rst | 4 ++-- docs/language/learn-ql/javascript/introduce-libraries-ts.rst | 4 ++-- docs/language/learn-ql/javascript/type-tracking.rst | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/language/learn-ql/javascript/ast-class-reference.rst b/docs/language/learn-ql/javascript/ast-class-reference.rst index 1b513b2d4ec..742ae5addb7 100644 --- a/docs/language/learn-ql/javascript/ast-class-reference.rst +++ b/docs/language/learn-ql/javascript/ast-class-reference.rst @@ -1,5 +1,5 @@ -AST class reference -=================== +Abstract syntax tree classes for JavaScript and TypeScript +========================================================== Statement classes ----------------- diff --git a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst index a2ff4309ee0..27c7b196ee8 100644 --- a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst +++ b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst @@ -1,5 +1,5 @@ -Data flow cheat sheet -===================== +Data flow cheat sheet for JavaScript +==================================== This page describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries. diff --git a/docs/language/learn-ql/javascript/flow-labels.rst b/docs/language/learn-ql/javascript/flow-labels.rst index c693319576d..83b57e7af01 100644 --- a/docs/language/learn-ql/javascript/flow-labels.rst +++ b/docs/language/learn-ql/javascript/flow-labels.rst @@ -1,5 +1,5 @@ -Tutorial: Precise data-flow analysis using flow labels -====================================================== +Using flow labels for precise data flow analysis +================================================ You can use basic inter-procedural data-flow analysis and taint tracking as described in :doc:`Analyzing data flow in JavaScript/TypeScript ` to check whether there is a path in diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index f01a8387a18..e3736349db6 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1,5 +1,5 @@ -Introducing the CodeQL libraries for JavaScript -=============================================== +CodeQL libraries for JavaScript +=============================== Overview -------- diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index e0c1ec748ff..14837f4202a 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -1,5 +1,5 @@ -Introducing the CodeQL libraries for TypeScript -=============================================== +CodeQL libraries for TypeScript +=============================== Overview -------- diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index f0dadd9ef70..eace393c0ee 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -1,5 +1,5 @@ -Tutorial: API modelling using type tracking -=========================================== +Using type tracking for API modeling +==================================== This tutorial demonstrates how to build a simple model of the Firebase API using the CodeQL type-tracking library for JavaScript. From 083dd4380b08c94e1a643f35d282b49dbb6de72b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 20 Feb 2020 16:55:21 +0100 Subject: [PATCH 042/459] Python: Add example for how to write your own sanitizer --- .../custom-sanitizer/SanitizedEdges.expected | 23 ++++ .../custom-sanitizer/SanitizedEdges.ql | 6 + .../examples/custom-sanitizer/Taint.qll | 73 ++++++++++++ .../custom-sanitizer/TestTaint.expected | 28 +++++ .../examples/custom-sanitizer/TestTaint.ql | 31 +++++ .../examples/custom-sanitizer/test.py | 110 ++++++++++++++++++ 6 files changed, 271 insertions(+) create mode 100644 python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.expected create mode 100644 python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.ql create mode 100644 python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll create mode 100644 python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.expected create mode 100644 python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql create mode 100644 python/ql/test/library-tests/examples/custom-sanitizer/test.py diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.expected b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.expected new file mode 100644 index 00000000000..22c6f68f1d7 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.expected @@ -0,0 +1,23 @@ +| MySanitizerHandlingNot | externally controlled string | test.py:13 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:18 | Pi(s_5) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:28 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:34 | Pi(s_10) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:40 | Pi(s_12) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:50 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:56 | Pi(s_10) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:62 | Pi(s_12) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:76 | Pi(s_3) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:82 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:87 | Pi(s_5) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:97 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:102 | Pi(s_7) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:107 | Pi(s_12) [true] | +| MySimpleSanitizer | externally controlled string | test.py:13 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:28 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:34 | Pi(s_10) [true] | +| MySimpleSanitizer | externally controlled string | test.py:50 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:56 | Pi(s_10) [true] | +| MySimpleSanitizer | externally controlled string | test.py:76 | Pi(s_3) [true] | +| MySimpleSanitizer | externally controlled string | test.py:97 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:102 | Pi(s_7) [true] | +| MySimpleSanitizer | externally controlled string | test.py:107 | Pi(s_12) [true] | diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.ql b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.ql new file mode 100644 index 00000000000..d523f79a963 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.ql @@ -0,0 +1,6 @@ +import python +import Taint + +from Sanitizer s, TaintKind taint, PyEdgeRefinement test +where s.sanitizingEdge(taint, test) +select s, taint, test.getTest().getLocation().toString(), test.getRepresentation() diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll new file mode 100644 index 00000000000..072737be2cd --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll @@ -0,0 +1,73 @@ +import python +import semmle.python.security.TaintTracking +import semmle.python.security.strings.Untrusted + +class SimpleSource extends TaintSource { + SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" } + + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } + + override string toString() { result = "taint source" } +} + +class MySimpleSanitizer extends Sanitizer { + MySimpleSanitizer() { this = "MySimpleSanitizer" } + + /** + * The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. + * + * Can't handle `if not is_safe(arg):` :\ that's why it's called MySimpleSanitizer + * + */ + override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { + taint instanceof ExternalStringKind and + exists(CallNode call | + test.getTest() = call and test.getSense() = true + | + call = Value::named("test.is_safe").getACall() and + test.getInput().getAUse() = call.getAnArg() + ) + } +} + +class MySanitizerHandlingNot extends Sanitizer { + MySanitizerHandlingNot() { this = "MySanitizerHandlingNot" } + + /** The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. */ + override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { + taint instanceof ExternalStringKind and + exists(CallNode call | + clears_taint_on_true(call, test.getTest(), test.getSense()) + | + call = Value::named("test.is_safe").getACall() and + test.getInput().getAUse() = call.getAnArg() + ) + } + + private predicate clears_taint_on_true(ControlFlowNode final_test, ControlFlowNode test, boolean sense) { + final_test = test and + sense = true + or + test.(UnaryExprNode).getNode().getOp() instanceof Not and + exists(ControlFlowNode nested_test | + nested_test = test.(UnaryExprNode).getOperand() and + clears_taint_on_true(final_test, nested_test, sense.booleanNot()) + ) + } +} + +class TestConfig extends TaintTracking::Configuration { + TestConfig() { this = "TestConfig" } + + override predicate isSanitizer(Sanitizer sanitizer) { + sanitizer instanceof MySanitizerHandlingNot + } + + override predicate isSource(TaintTracking::Source source) { + source instanceof SimpleSource + } + + override predicate isSink(TaintTracking::Sink sink) { + none() + } +} diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.expected b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.expected new file mode 100644 index 00000000000..269eb47a37f --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.expected @@ -0,0 +1,28 @@ +| test.py:14 | test_basic | s | | ok | +| test.py:16 | test_basic | s | externally controlled string | ok | +| test.py:19 | test_basic | s | externally controlled string | ok | +| test.py:21 | test_basic | s | | ok | +| test.py:29 | test_or | s | externally controlled string | ok | +| test.py:31 | test_or | s | externally controlled string | ok | +| test.py:35 | test_or | s | externally controlled string | ok | +| test.py:37 | test_or | s | externally controlled string | ok | +| test.py:41 | test_or | s | externally controlled string | ok | +| test.py:43 | test_or | s | externally controlled string | ok | +| test.py:51 | test_and | s | | ok | +| test.py:53 | test_and | s | externally controlled string | ok | +| test.py:57 | test_and | s | externally controlled string | ok | +| test.py:59 | test_and | s | | ok | +| test.py:63 | test_and | s | externally controlled string | ok | +| test.py:65 | test_and | s | | ok | +| test.py:73 | test_tricky | s | externally controlled string | failure | +| test.py:77 | test_tricky | s_ | externally controlled string | failure | +| test.py:83 | test_nesting_not | s | | ok | +| test.py:85 | test_nesting_not | s | externally controlled string | ok | +| test.py:88 | test_nesting_not | s | externally controlled string | ok | +| test.py:90 | test_nesting_not | s | | ok | +| test.py:98 | test_nesting_not_with_and_true | s | externally controlled string | ok | +| test.py:100 | test_nesting_not_with_and_true | s | | ok | +| test.py:103 | test_nesting_not_with_and_true | s | | ok | +| test.py:105 | test_nesting_not_with_and_true | s | externally controlled string | ok | +| test.py:108 | test_nesting_not_with_and_true | s | externally controlled string | ok | +| test.py:110 | test_nesting_not_with_and_true | s | | ok | diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql new file mode 100644 index 00000000000..81357d18fc7 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql @@ -0,0 +1,31 @@ +import python +import semmle.python.security.TaintTracking +import Taint + +from Call call, Expr arg, + boolean expected_taint, boolean has_taint, string test_res, + string taint_string +where + call.getLocation().getFile().getShortName() = "test.py" and + ( + call.getFunc().(Name).getId() = "ensure_tainted" and + expected_taint = true + or + call.getFunc().(Name).getId() = "ensure_not_tainted" and + expected_taint = false + ) and + arg = call.getAnArg() and + ( + not exists(TaintedNode tainted | tainted.getAstNode() = arg) and + taint_string = "" and + has_taint = false + or + exists(TaintedNode tainted | tainted.getAstNode() = arg | + taint_string = tainted.getTaintKind().toString() + ) and + has_taint = true + ) and + if expected_taint = has_taint then test_res = "ok" else test_res = "failure" + // if expected_taint = has_taint then test_res = "✓" else test_res = "✕" +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string, test_res diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/test.py b/python/ql/test/library-tests/examples/custom-sanitizer/test.py new file mode 100644 index 00000000000..e0bf29f4ee6 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/test.py @@ -0,0 +1,110 @@ +def random_choice(): + return bool(GLOBAL_UNKOWN_VAR) + +def is_safe(arg): + return UNKNOWN_FUNC(arg) + +def true_func(): + return True + +def test_basic(): + s = TAINTED_STRING + + if is_safe(s): + ensure_not_tainted(s) + else: + ensure_tainted(s) + + if not is_safe(s): + ensure_tainted(s) + else: + ensure_not_tainted(s) + + +def test_or(): + s = TAINTED_STRING + + # x or y + if is_safe(s) or random_choice(): + ensure_tainted(s) # might be tainted + else: + ensure_tainted(s) # must be tainted + + # not (x or y) + if not(is_safe(s) or random_choice()): + ensure_tainted(s) # must be tainted + else: + ensure_tainted(s) # might be tainted + + # not (x or y) == not x and not y [de Morgan's laws] + if not is_safe(s) and not random_choice(): + ensure_tainted(s) # must be tainted + else: + ensure_tainted(s) # might be tainted + + +def test_and(): + s = TAINTED_STRING + + # x and y + if is_safe(s) and random_choice(): + ensure_not_tainted(s) # must not be tainted + else: + ensure_tainted(s) # might be tainted + + # not (x and y) + if not(is_safe(s) and random_choice()): + ensure_tainted(s) # might be tainted + else: + ensure_not_tainted(s) + + # not (x and y) == not x or not y [de Morgan's laws] + if not is_safe(s) or not random_choice(): + ensure_tainted(s) # might be tainted + else: + ensure_not_tainted(s) + + +def test_tricky(): + s = TAINTED_STRING + + x = is_safe(s) + if x: + ensure_not_tainted(s) # FP + + s_ = s + if is_safe(s): + ensure_not_tainted(s_) # FP + +def test_nesting_not(): + s = TAINTED_STRING + + if not(not(is_safe(s))): + ensure_not_tainted(s) + else: + ensure_tainted(s) + + if not(not(not(is_safe(s)))): + ensure_tainted(s) + else: + ensure_not_tainted(s) + +# Adding `and True` makes the sanitizer trigger when it would otherwise not. See output in +# SanitizedEdges.expected and compare with `test_nesting_not` and `test_basic` +def test_nesting_not_with_and_true(): + s = TAINTED_STRING + + if not(is_safe(s) and True): + ensure_tainted(s) + else: + ensure_not_tainted(s) + + if not(not(is_safe(s) and True)): + ensure_not_tainted(s) + else: + ensure_tainted(s) + + if not(not(not(is_safe(s) and True))): + ensure_tainted(s) + else: + ensure_not_tainted(s) From b4c72f610a59ae4711bf46f6d07c7b001719f9c5 Mon Sep 17 00:00:00 2001 From: mchammer01 <42146119+mchammer01@users.noreply.github.com> Date: Fri, 21 Feb 2020 14:51:38 +0000 Subject: [PATCH 043/459] pre-migration tasks: start adding intros --- docs/language/learn-ql/javascript/flow-labels.rst | 4 ++-- .../language/learn-ql/javascript/introduce-libraries-js.rst | 6 ++++-- .../language/learn-ql/javascript/introduce-libraries-ts.rst | 6 ++++-- docs/language/learn-ql/javascript/ql-for-javascript.rst | 4 +++- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/language/learn-ql/javascript/flow-labels.rst b/docs/language/learn-ql/javascript/flow-labels.rst index 83b57e7af01..2a2caee9040 100644 --- a/docs/language/learn-ql/javascript/flow-labels.rst +++ b/docs/language/learn-ql/javascript/flow-labels.rst @@ -390,8 +390,8 @@ tainted objects from partially tainted objects. The `Uncontrolled data used in p `_ query uses four flow labels to track whether a user-controlled string may be an absolute path and whether it may contain ``..`` components. -What next? ----------- +Further reading +--------------- - Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`Introducing the JavaScript libraries `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index e3736349db6..22aa5066b87 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1,6 +1,8 @@ CodeQL libraries for JavaScript =============================== +This article is an overview of the extensive libraries you can use to analyze databases generated from JavaScript codebases. Using thes libraries makes it easier for you to write queries. + Overview -------- @@ -1026,8 +1028,8 @@ Alias nodes are represented by class `YAMLAliasNode `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index 14837f4202a..6c2a1b13441 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -1,6 +1,8 @@ CodeQL libraries for TypeScript =============================== +This article is an overview of the libraries you can use to analyze databases generated from TypeScript codebases. Using thes libraries makes it easier for you to write queries. + Overview -------- @@ -444,8 +446,8 @@ A `LocalNamespaceName `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/javascript/ql-for-javascript.rst b/docs/language/learn-ql/javascript/ql-for-javascript.rst index d2d864cc072..476e43a6671 100644 --- a/docs/language/learn-ql/javascript/ql-for-javascript.rst +++ b/docs/language/learn-ql/javascript/ql-for-javascript.rst @@ -1,6 +1,8 @@ CodeQL for JavaScript ===================== +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from JavaScript codebases. + .. toctree:: :glob: :hidden: @@ -29,7 +31,7 @@ These documents provide an overview of the CodeQL libraries for JavaScript and T - :doc:`Data flow cheat sheet ` lists parts of the CodeQL libraries that are commonly used for variant analysis and in data flow queries. -Other resources +Further reading --------------- - For examples of how to query common JavaScript elements, see the `JavaScript cookbook `__. From b622e2ae06b61c2e418e7705da424e4f0feebd04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Fri, 21 Feb 2020 17:51:15 +0100 Subject: [PATCH 044/459] Java: Calling openStream on URLs created from remote source can lead to local file disclosure. --- .../src/Security/CWE/CWE-036/OpenStream.java | 8 +++ .../src/Security/CWE/CWE-036/OpenStream.qhelp | 39 +++++++++++++++ .../ql/src/Security/CWE/CWE-036/OpenStream.ql | 50 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 java/ql/src/Security/CWE/CWE-036/OpenStream.java create mode 100644 java/ql/src/Security/CWE/CWE-036/OpenStream.qhelp create mode 100644 java/ql/src/Security/CWE/CWE-036/OpenStream.ql diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.java b/java/ql/src/Security/CWE/CWE-036/OpenStream.java new file mode 100644 index 00000000000..c7f7e910c0f --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-036/OpenStream.java @@ -0,0 +1,8 @@ +public class TestServlet extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // BAD: a URL from a remote source is opened with URL#openStream() + URL url = new URL(request.getParameter("url")); + InputStream inputStream = new URL(url).openStream(); + } +} diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/Security/CWE/CWE-036/OpenStream.qhelp new file mode 100644 index 00000000000..83ce2a6a17f --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-036/OpenStream.qhelp @@ -0,0 +1,39 @@ + + + +

Calling openStream on URLs created from remote source can lead to local file disclosure.

+ +

If openStream is called on a java.net.URL, that was created from a remote source +an attacker can try to pass absolute URLs starting with file:// or jar:// to access +local resources in addition to remote ones.

+ +
+ + +

When you construct a URL using java.net.URL from a remote source, make sure +to not call openStream on it. Instead fetch the URL with a HTTP Client to access its content. +Also validate that the URL uses the correct protocol and host combination.

+ +
+ + +

The following example shows an URL that is constructed from a request parameter. Afterwards openStream +is called on the URL, potentially leading to a local file access.

+ + + +
+ + +
  • Java Platform, Standard Edition 11, API Specification: + +Class URL.
  • +
  • + + + + + diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/Security/CWE/CWE-036/OpenStream.ql new file mode 100644 index 00000000000..bfca30c5c83 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-036/OpenStream.ql @@ -0,0 +1,50 @@ +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.FlowSources +import DataFlow::PathGraph + +class URLConstructor extends ClassInstanceExpr { + URLConstructor() { this.getConstructor().getDeclaringType().getQualifiedName() = "java.net.URL" } + + Expr stringArg() { + // Query only in URL's that were constructed by calling the single parameter string constructor. + if + this.getConstructor().getNumberOfParameters() = 1 and + this.getConstructor().getParameter(0).getType().getName() = "String" + then result = this.getArgument(0) + else none() + } +} + +class URLOpenStreamMethod extends Method { + URLOpenStreamMethod() { + this.getDeclaringType().getQualifiedName() = "java.net.URL" and + this.getName() = "openStream" + } +} + +class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration { + RemoteURLToOpenStreamFlowConfig() { this = "OpenStream::RemoteURLToOpenStreamFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess m | + sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenStreamMethod + ) + } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(URLConstructor u | + node1.asExpr() = u.stringArg() and + node2.asExpr() = u + ) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess call +where + sink.getNode().asExpr() = call.getQualifier() and + any(RemoteURLToOpenStreamFlowConfig c).hasFlowPath(source, sink) +select call, source, sink, + "URL on which openStream is called may have been constructed from remote source" From 9de2be8ebaf652b6d91878fcfc969dfac57bdb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Fri, 21 Feb 2020 17:13:04 +0000 Subject: [PATCH 045/459] Fix whitespace issues in OpenStream.java --- java/ql/src/Security/CWE/CWE-036/OpenStream.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.java b/java/ql/src/Security/CWE/CWE-036/OpenStream.java index c7f7e910c0f..d0772b8cdbd 100644 --- a/java/ql/src/Security/CWE/CWE-036/OpenStream.java +++ b/java/ql/src/Security/CWE/CWE-036/OpenStream.java @@ -1,8 +1,8 @@ public class TestServlet extends HttpServlet { - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - // BAD: a URL from a remote source is opened with URL#openStream() + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // BAD: a URL from a remote source is opened with URL#openStream() URL url = new URL(request.getParameter("url")); InputStream inputStream = new URL(url).openStream(); - } + } } From e1e03e326bac461f113de93738114b68a7bc8be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Fri, 21 Feb 2020 18:22:05 +0000 Subject: [PATCH 046/459] Add query documentation header --- java/ql/src/Security/CWE/CWE-036/OpenStream.ql | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/Security/CWE/CWE-036/OpenStream.ql index bfca30c5c83..21fab57d45d 100644 --- a/java/ql/src/Security/CWE/CWE-036/OpenStream.ql +++ b/java/ql/src/Security/CWE/CWE-036/OpenStream.ql @@ -1,3 +1,11 @@ +/** + * @name Calling openStream on URLs created from remote source can lead to file disclosure + * @description If openStream is called on a java.net.URL, that was created from a remote source + * an attacker can try to pass absolute URLs starting with file:// or jar:// to access + * local resources in addition to remote ones. + * @kind path-problem + */ + import java import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources From e81d3ce0b40764e8d660000369233453d78ea66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Sun, 23 Feb 2020 12:35:03 +0100 Subject: [PATCH 047/459] Add type for java.net.URL --- java/ql/src/Security/CWE/CWE-036/OpenStream.ql | 4 ++-- java/ql/src/semmle/code/java/frameworks/Networking.qll | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/Security/CWE/CWE-036/OpenStream.ql index 21fab57d45d..6cf5960a55c 100644 --- a/java/ql/src/Security/CWE/CWE-036/OpenStream.ql +++ b/java/ql/src/Security/CWE/CWE-036/OpenStream.ql @@ -12,7 +12,7 @@ import semmle.code.java.dataflow.FlowSources import DataFlow::PathGraph class URLConstructor extends ClassInstanceExpr { - URLConstructor() { this.getConstructor().getDeclaringType().getQualifiedName() = "java.net.URL" } + URLConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUrl } Expr stringArg() { // Query only in URL's that were constructed by calling the single parameter string constructor. @@ -26,7 +26,7 @@ class URLConstructor extends ClassInstanceExpr { class URLOpenStreamMethod extends Method { URLOpenStreamMethod() { - this.getDeclaringType().getQualifiedName() = "java.net.URL" and + this.getDeclaringType() instanceof TypeUrl and this.getName() = "openStream" } } diff --git a/java/ql/src/semmle/code/java/frameworks/Networking.qll b/java/ql/src/semmle/code/java/frameworks/Networking.qll index 3889c5a8b5d..92575995636 100644 --- a/java/ql/src/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/src/semmle/code/java/frameworks/Networking.qll @@ -12,6 +12,10 @@ class TypeSocket extends RefType { TypeSocket() { hasQualifiedName("java.net", "Socket") } } +class TypeUrl extends RefType { + TypeUrl() { hasQualifiedName("java.net", "URL") } +} + class URLConnectionGetInputStreamMethod extends Method { URLConnectionGetInputStreamMethod() { getDeclaringType() instanceof TypeUrlConnection and From 0c5216570c5a507c164d3cfe2a7ece8b4780a051 Mon Sep 17 00:00:00 2001 From: mchammer01 <42146119+mchammer01@users.noreply.github.com> Date: Tue, 25 Feb 2020 04:50:14 -0800 Subject: [PATCH 048/459] pre-migration work: fix typos --- docs/language/learn-ql/javascript/introduce-libraries-js.rst | 2 +- docs/language/learn-ql/javascript/introduce-libraries-ts.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 22aa5066b87..8554694c97f 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1,7 +1,7 @@ CodeQL libraries for JavaScript =============================== -This article is an overview of the extensive libraries you can use to analyze databases generated from JavaScript codebases. Using thes libraries makes it easier for you to write queries. +This article is an overview of the extensive libraries you can use to analyze databases generated from JavaScript codebases. Using the libraries makes it easier for you to write queries. Overview -------- diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index 6c2a1b13441..9ec81a76bf1 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -1,7 +1,7 @@ CodeQL libraries for TypeScript =============================== -This article is an overview of the libraries you can use to analyze databases generated from TypeScript codebases. Using thes libraries makes it easier for you to write queries. +This article is an overview of the libraries you can use to analyze databases generated from TypeScript codebases. Using the libraries makes it easier for you to write queries. Overview -------- From ce70b86604c3b3f53c3eb9c7a3d78deac67788b3 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Feb 2020 14:17:07 +0100 Subject: [PATCH 049/459] Java: Add data-flow consistency checks. --- .../internal/DataFlowImplConsistency.qll | 127 ++++++++++++++++++ .../dataflow/internal/DataFlowPrivate.qll | 11 ++ .../java/dataflow/internal/DataFlowUtil.qll | 5 +- 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..88daa8dd6fe --- /dev/null +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,127 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import TaintTrackingUtil + +module Consistency { + private predicate relevantNode(Node n) { + n instanceof ArgumentNode or + n instanceof ParameterNode or + n instanceof ReturnNode or + n = getAnOutNode(_, _) or + simpleLocalFlowStep(n, _) or + simpleLocalFlowStep(_, n) or + jumpStep(n, _) or + jumpStep(_, n) or + storeStep(n, _, _) or + storeStep(_, _, n) or + readStep(n, _, _) or + readStep(_, _, n) or + defaultAdditionalTaintStep(n, _) or + defaultAdditionalTaintStep(_, n) + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + relevantNode(n) and + c = count(n.getEnclosingCallable()) and + c != 1 and + if c > 1 + then msg = "Node does not have unique enclosing callable." + else msg = "Node is missing an enclosing callable." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + relevantNode(n) and + c = count(n.getTypeBound()) and + c != 1 and + if c > 1 + then msg = "Node does not have unique type bound." + else msg = "Node is missing a type bound." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + relevantNode(n) and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + if c > 1 + then msg = "Node does not have unique type representation." + else msg = "Node is missing a type representation." + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 27d80d8df8d..eaa768d68a6 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -326,3 +326,14 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { } int accessPathLimit() { result = 5 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { + n.getType() instanceof ImmutableType or n instanceof ImplicitVarargsArray +} 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 4eb9b51a74a..74b492f76bb 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll @@ -11,7 +11,10 @@ import semmle.code.java.dataflow.InstanceAccess cached private newtype TNode = - TExprNode(Expr e) or + TExprNode(Expr e) { + not e.getType() instanceof VoidType and + not e.getParent*() instanceof Annotation + } or TExplicitParameterNode(Parameter p) { exists(p.getCallable().getBody()) } or TImplicitVarargsArray(Call c) { c.getCallee().isVarargs() and From a09e47903384b49fde1ea366f120e102ae65b8bc Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 27 Feb 2020 10:14:14 +0100 Subject: [PATCH 050/459] Java: Change relevantNode to a class, and add two more checks. --- .../internal/DataFlowImplConsistency.qll | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index 88daa8dd6fe..b72f29164f1 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -8,26 +8,28 @@ private import DataFlowImplSpecific::Public private import TaintTrackingUtil module Consistency { - private predicate relevantNode(Node n) { - n instanceof ArgumentNode or - n instanceof ParameterNode or - n instanceof ReturnNode or - n = getAnOutNode(_, _) or - simpleLocalFlowStep(n, _) or - simpleLocalFlowStep(_, n) or - jumpStep(n, _) or - jumpStep(_, n) or - storeStep(n, _, _) or - storeStep(_, _, n) or - readStep(n, _, _) or - readStep(_, _, n) or - defaultAdditionalTaintStep(n, _) or - defaultAdditionalTaintStep(_, n) + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } } query predicate uniqueEnclosingCallable(Node n, string msg) { exists(int c | - relevantNode(n) and + n instanceof RelevantNode and c = count(n.getEnclosingCallable()) and c != 1 and if c > 1 @@ -38,7 +40,7 @@ module Consistency { query predicate uniqueTypeBound(Node n, string msg) { exists(int c | - relevantNode(n) and + n instanceof RelevantNode and c = count(n.getTypeBound()) and c != 1 and if c > 1 @@ -49,7 +51,7 @@ module Consistency { query predicate uniqueTypeRepr(Node n, string msg) { exists(int c | - relevantNode(n) and + n instanceof RelevantNode and c = count(getErasedRepr(n.getTypeBound())) and c != 1 and if c > 1 @@ -101,6 +103,21 @@ module Consistency { n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." } + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + if c > 1 + then msg = "PostUpdateNode does not have unique pre-update node." + else msg = "PostUpdateNode is missing a pre-update node." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and msg = "PostUpdateNode does not share callable with its pre-update node." From 8e2b56cfd0058d064c8cde0b4c88575ae6fc29d7 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 27 Feb 2020 13:10:42 +0100 Subject: [PATCH 051/459] Java: Include count in messages. --- .../internal/DataFlowImplConsistency.qll | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index b72f29164f1..45f2a5784b8 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -32,9 +32,7 @@ module Consistency { n instanceof RelevantNode and c = count(n.getEnclosingCallable()) and c != 1 and - if c > 1 - then msg = "Node does not have unique enclosing callable." - else msg = "Node is missing an enclosing callable." + msg = "Node should have one enclosing callable but has " + c + "." ) } @@ -43,9 +41,7 @@ module Consistency { n instanceof RelevantNode and c = count(n.getTypeBound()) and c != 1 and - if c > 1 - then msg = "Node does not have unique type bound." - else msg = "Node is missing a type bound." + msg = "Node should have one type bound but has " + c + "." ) } @@ -54,9 +50,7 @@ module Consistency { n instanceof RelevantNode and c = count(getErasedRepr(n.getTypeBound())) and c != 1 and - if c > 1 - then msg = "Node does not have unique type representation." - else msg = "Node is missing a type representation." + msg = "Node should have one type representation but has " + c + "." ) } @@ -107,9 +101,7 @@ module Consistency { exists(int c | c = count(n.getPreUpdateNode()) and c != 1 and - if c > 1 - then msg = "PostUpdateNode does not have unique pre-update node." - else msg = "PostUpdateNode is missing a pre-update node." + msg = "PostUpdateNode should have one pre-update node but has " + c + "." ) } From 67d386b5babef19440d8635a521ebd8f64486350 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 27 Feb 2020 13:24:33 +0100 Subject: [PATCH 052/459] C++/C#: Add synchronization. --- config/identical-files.json | 6 + .../internal/DataFlowImplConsistency.qll | 136 ++++++++++++++++++ .../cpp/dataflow/internal/DataFlowPrivate.qll | 9 ++ .../internal/DataFlowImplConsistency.qll | 136 ++++++++++++++++++ .../ir/dataflow/internal/DataFlowPrivate.qll | 9 ++ .../internal/DataFlowImplConsistency.qll | 136 ++++++++++++++++++ .../dataflow/internal/DataFlowPrivate.qll | 9 ++ 7 files changed, 441 insertions(+) create mode 100644 cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll create mode 100644 cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll diff --git a/config/identical-files.json b/config/identical-files.json index 47b37455b8c..b16b61df654 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -39,6 +39,12 @@ "java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll" ], + "DataFlow Java/C++/C# Consistency checks": [ + "java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", + "cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll", + "cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", + "csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll" + ], "C++ SubBasicBlocks": [ "cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll", "cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll" diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..45f2a5784b8 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,136 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import TaintTrackingUtil + +module Consistency { + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getEnclosingCallable()) and + c != 1 and + msg = "Node should have one enclosing callable but has " + c + "." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getTypeBound()) and + c != 1 and + msg = "Node should have one type bound but has " + c + "." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + msg = "Node should have one type representation but has " + c + "." + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + msg = "PostUpdateNode should have one pre-update node but has " + c + "." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index a0fd5dc4c50..514bfd6261d 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -293,3 +293,12 @@ class DataFlowCall extends Expr { predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation int accessPathLimit() { result = 5 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { none() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..45f2a5784b8 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,136 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import TaintTrackingUtil + +module Consistency { + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getEnclosingCallable()) and + c != 1 and + msg = "Node should have one enclosing callable but has " + c + "." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getTypeBound()) and + c != 1 and + msg = "Node should have one type bound but has " + c + "." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + msg = "Node should have one type representation but has " + c + "." + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + msg = "PostUpdateNode should have one pre-update node but has " + c + "." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 83e5d5eb06b..bb76bc6370c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -202,3 +202,12 @@ class DataFlowCall extends CallInstruction { predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation int accessPathLimit() { result = 5 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { none() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..45f2a5784b8 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,136 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import TaintTrackingUtil + +module Consistency { + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getEnclosingCallable()) and + c != 1 and + msg = "Node should have one enclosing callable but has " + c + "." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getTypeBound()) and + c != 1 and + msg = "Node should have one type bound but has " + c + "." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + msg = "Node should have one type representation but has " + c + "." + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + msg = "PostUpdateNode should have one pre-update node but has " + c + "." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} 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 22684e34b48..4a6693fbebf 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1499,3 +1499,12 @@ private predicate viableConstantBooleanParamArg( } int accessPathLimit() { result = 3 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { none() } From 7a2bb120ecd9567fbacea0a297debec8e3adc855 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Mon, 2 Mar 2020 14:50:52 +0000 Subject: [PATCH 053/459] Update introductions for feedback --- docs/language/learn-ql/python/control-flow.rst | 5 ++++- docs/language/learn-ql/python/functions.rst | 2 +- docs/language/learn-ql/python/introduce-libraries-python.rst | 4 ++-- docs/language/learn-ql/python/pointsto-type-infer.rst | 5 +---- docs/language/learn-ql/python/statements-expressions.rst | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index 736bb89f08b..d1645315784 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -1,7 +1,10 @@ Analyzing control flow in Python ================================ -You can write CodeQL queries to explore the control flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. +You can write CodeQL queries to explore the control-flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. + +About analyzing control flow +-------------------------------------- To analyze the control-flow graph of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. For more information, see `Control-flow graph `__ on Wikipedia. diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index a58f7ef889a..8fa89f5e188 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -1,7 +1,7 @@ Functions in Python =================== -Functions are key building blocks of Python code bases. You can use syntactic classes from the standard CodeQL library to find functions and identify calls to them. +You can use syntactic classes from the standard CodeQL library to find Python functions and identify calls to them. These examples use the standard CodeQL class `Function `__. For more information, see ":doc:`Introducing the Python libraries `." diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 44818219bb6..80944b852a2 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -1,12 +1,12 @@ CodeQL library for Python ========================= -This is an overview of the extensive library you use to analyze databases generated from Python code bases. Using this library makes it easier for you to write queries. +When you need to analyze a Python program, you can make use of the large collection of classes in the Python library for CodeQL. About the CodeQL library for Python ----------------------------------- -The CodeQL library for each programming language uses classes with abstractions and predicates to present data in an object-oriented form. +The CodeQL library for each programming language uses classes with abstractions and predicates to present data in an object-oriented form. Each CodeQL library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index 6dfee9f4bbb..40f2ecb81ff 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -1,10 +1,7 @@ Pointer analysis and type inference in Python ============================================= -At runtime, each Python expression has a value with an associated type. You can learn how an expression behaves at runtime using type-inference classes from the standard CodeQL library. - - -This topic contains worked examples of how to write queries using the standard CodeQL library classes for Python type inference. +At runtime, each Python expression has a value with an associated type. You can learn how an expression behaves at runtime by using type-inference classes from the standard CodeQL library. The ``Value`` class -------------------- diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 209d22ae3d1..eda2d1e4578 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -1,7 +1,7 @@ Expressions and statements in Python ==================================== -Expressions define a value. Statements represent a command or action. You can explore how they are used in a code base using syntactic classes from the standard CodeQL library. +You can use syntactic classes from the CodeQL library to explore how Python expressions and statements are used in a code base. Statements ---------- From daf5a96935311c05bd53975800b15b121a17a27c Mon Sep 17 00:00:00 2001 From: Alistair Christie Date: Mon, 2 Mar 2020 15:07:30 +0000 Subject: [PATCH 054/459] Make review comment changes --- docs/language/learn-ql/java/annotations.rst | 10 ++++--- .../learn-ql/java/ast-class-reference.rst | 6 ++--- docs/language/learn-ql/java/call-graph.rst | 12 ++++----- docs/language/learn-ql/java/dataflow.rst | 2 +- .../learn-ql/java/expressions-statements.rst | 8 +++--- .../java/introduce-libraries-java.rst | 26 +++++++++---------- docs/language/learn-ql/java/javadoc.rst | 4 +-- .../learn-ql/java/source-locations.rst | 4 +-- .../learn-ql/java/types-class-hierarchy.rst | 8 +++--- 9 files changed, 41 insertions(+), 39 deletions(-) diff --git a/docs/language/learn-ql/java/annotations.rst b/docs/language/learn-ql/java/annotations.rst index 26ade9dbd80..a8c5fe93aa1 100644 --- a/docs/language/learn-ql/java/annotations.rst +++ b/docs/language/learn-ql/java/annotations.rst @@ -167,7 +167,7 @@ Now we can define a class for representing deprecated methods: } } -Finally, we use these classes to find calls to deprecated methods, excluding calls that themselves appear in deprecated methods (see :doc:`Tutorial: Navigating the call graph ` for more information on class ``Call``): +Finally, we use these classes to find calls to deprecated methods, excluding calls that themselves appear in deprecated methods: .. code-block:: ql @@ -178,7 +178,9 @@ Finally, we use these classes to find calls to deprecated methods, excluding cal and not call.getCaller() instanceof DeprecatedMethod select call, "This call invokes a deprecated method." -On our example, this query flags the call to ``A.m`` in ``A.r``, but not the one in ``A.n``. +In our example, this query flags the call to ``A.m`` in ``A.r``, but not the one in ``A.n``. + +For more information about the class ``Call``, see :doc:`Navigating the call graph `. Improvements ~~~~~~~~~~~~ @@ -238,6 +240,6 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress Further reading --------------- -- Take a look at some of the other tutorials: :doc:`Tutorial: Javadoc ` and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. +- Take a look at some of the other articles in this section: :doc:`Javadoc ` and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/java/ast-class-reference.rst b/docs/language/learn-ql/java/ast-class-reference.rst index aac764411ad..f34e2eec764 100644 --- a/docs/language/learn-ql/java/ast-class-reference.rst +++ b/docs/language/learn-ql/java/ast-class-reference.rst @@ -1,7 +1,7 @@ -Abstract syntax tree classes in Java -==================================== +Classes for working with Java code +================================== -CodeQL has a large selection of classes for working with Java code. +CodeQL has a large selection of classes for working with Java statements and expressions. .. _Expr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Expr.html .. _Stmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index 6f4862c8fc6..ab32cebdc8e 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -1,10 +1,10 @@ Navigating the call graph ========================= -CodeQL provides an API for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used. +CodeQL has classes for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used. -Call graph API --------------- +Call graph classes +------------------ The CodeQL library for Java provides two abstract classes for representing a program's call graph: ``Callable`` and ``Call``. The former is simply the common superclass of ``Method`` and ``Constructor``, the latter is a common superclass of ``MethodAccess``, ``ClassInstanceExpression``, ``ThisConstructorInvocationStmt`` and ``SuperConstructorInvocationStmt``. Simply put, a ``Callable`` is something that can be invoked, and a ``Call`` is something that invokes a ``Callable``. @@ -68,7 +68,7 @@ In our example, ``Client.main`` calls the constructor ``Sub(int)`` and the metho Example: Finding unused methods ------------------------------- -Given this API, we can easily write a query that finds methods that are not called by any other method: +We can use the ``Callable`` class to write a query that finds methods that are not called by any other method: .. code-block:: ql @@ -164,6 +164,6 @@ Finally, on many Java projects there are methods that are invoked indirectly by Further reading --------------- -- Find out how to query metadata and white space: :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. +- Find out how to query metadata and white space: :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index 5767956d2d8..51f186bbb22 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -256,7 +256,7 @@ Exercise 4: Using the answers from 2 and 3, write a query which finds all global What next? ---------- -- Try the worked examples in these articles: :doc:`Tutorial: Navigating the call graph ` and :doc:`Tutorial: Working with source locations `. +- Try the worked examples in these articles: :doc:`Navigating the call graph ` and :doc:`Working with source locations `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index 687f43213f1..caa6c400852 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -1,4 +1,4 @@ -Expressions and statements in Java +Overflow-prone comparisons in Java ================================== You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow. @@ -26,7 +26,7 @@ If ``l`` is bigger than 2\ :sup:`31`\ - 1 (the largest positive value of type `` All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an "overflow"). For ``int``, this maximum value is 2\ :sup:`31`\ - 1. Type ``long`` can accommodate larger values up to a maximum of 2\ :sup:`63`\ - 1. In this example, this means that ``l`` can take on a value that is higher than the maximum for type ``int``; ``i`` will never be able to reach this value, instead overflowing and returning to a low value. -We're going to develop a query that finds code that looks like it might exhibit this kind of behavior. We'll be using several of the standard library classes for representing statements and functions, a full list of which can be found in the :doc:`AST class reference `. +We're going to develop a query that finds code that looks like it might exhibit this kind of behavior. We'll be using several of the standard library classes for representing statements and functions. For a full list, see :doc:`Classes for working with Java code `. Initial query ------------- @@ -125,6 +125,6 @@ Now we rewrite our query to make use of these new classes: Further reading --------------- -- Have a look at some of the other tutorials: :doc:`Tutorial: Types and the class hierarchy `, :doc:`Tutorial: Navigating the call graph `, :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. +- Have a look at some of the other articles in this section: :doc:`Java types `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index c424b558224..8948f388ed9 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -1,10 +1,10 @@ CodeQL library for Java ======================= -When you need to analyze a Java program, you can make use of the large collection of classes in the Java library for CodeQL. +When you're analyzing a Java program in {{ site.data.variables.product.prodname_dotcom }}, you can make use of the large collection of classes in the CodeQL library for Java. -About the Java library ----------------------- +About the CodeQL library for Java +--------------------------------- There is an extensive library for analyzing CodeQL databases extracted from Java projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. @@ -14,13 +14,13 @@ The library is implemented as a set of QL modules, that is, files with the exten import java -The rest of this topic briefly summarizes the most important classes and predicates provided by this library. +The rest of this article briefly summarizes the most important classes and predicates provided by this library. .. pull-quote:: Note - The example queries in this topic illustrate the types of results returned by different library classes. The results themselves are not interesting but can be used as the basis for developing a more complex query. The tutorial topics show how you can take a simple query and fine-tune it to find precisely the results you're interested in. + The example queries in this article illustrate the types of results returned by different library classes. The results themselves are not interesting but can be used as the basis for developing a more complex query. The other articles in this section of the help show how you can take a simple query and fine-tune it to find precisely the results you're interested in. Summary of the library classes ------------------------------ @@ -196,7 +196,7 @@ The wildcards ``? extends Number`` and ``? super Float`` are represented by clas For dealing with generic methods, there are classes ``GenericMethod``, ``ParameterizedMethod`` and ``RawMethod``, which are entirely analogous to the like-named classes for representing generic types. -For more information on working with types, see the :doc:`tutorial on types and the class hierarchy `. +For more information on working with types, see the :doc:`article on Java types `. Variables ~~~~~~~~~ @@ -210,7 +210,7 @@ Class ``Variable`` represents a variable `in the Java sense ` for an exhaustive list of all expression and statement types available in the standard QL library. +Classes in this category represent abstract syntax tree (AST) nodes, that is, statements (class ``Stmt``) and expressions (class ``Expr``). For a full list of expression and statement types available in the standard QL library, see :doc:`Classes for working with Java code `. Both ``Expr`` and ``Stmt`` provide member predicates for exploring the abstract syntax tree of a program: @@ -260,7 +260,7 @@ Finally, here is a query that finds method bodies: As these examples show, the parent node of an expression is not always an expression: it may also be a statement, for example, an ``IfStmt``. Similarly, the parent node of a statement is not always a statement: it may also be a method or a constructor. To capture this, the QL Java library provides two abstract class ``ExprParent`` and ``StmtParent``, the former representing any node that may be the parent node of an expression, and the latter any node that may be the parent node of a statement. -For more information on working with AST classes, see the :doc:`tutorial on expressions and statements `. +For more information on working with AST classes, see the :doc:`article on overflow-prone comparisons in Java `. Metadata -------- @@ -292,7 +292,7 @@ These annotations are represented by class ``Annotation``. An annotation is simp ➤ `See this in the query console `__. Only constructors with the ``@deprecated`` annotation are reported this time. -For more information on working with annotations, see the :doc:`tutorial on annotations `. +For more information on working with annotations, see the :doc:`article on annotations `. For Javadoc, class ``Element`` has a member predicate ``getDoc`` that returns a delegate ``Documentable`` object, which can then be queried for its attached Javadoc comments. For example, the following query finds Javadoc comments on private fields: @@ -327,7 +327,7 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle On line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment. -For more information on working with Javadoc, see the :doc:`tutorial on Javadoc `. +For more information on working with Javadoc, see the :doc:`article on Javadoc `. Metrics ------- @@ -381,11 +381,11 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So ➤ `See this in the query console `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph `. -For more information about callables and calls, see the :doc:`call graph tutorial `. +For more information about callables and calls, see the :doc:`article on the call graph `. Further reading --------------- -- Experiment with the worked examples in the CodeQL for Java tutorial topics: :doc:`Types and the class hierarchy `, :doc:`Expressions and statements `, :doc:`Navigating the call graph `, :doc:`Annotations `, :doc:`Javadoc ` and :doc:`Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. +- Experiment with the worked examples in the CodeQL for Java articles: :doc:`Java types `, :doc:`Overflow-prone comparisons in Java `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc ` and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/java/javadoc.rst b/docs/language/learn-ql/java/javadoc.rst index efdd5ba8d1a..c484c480291 100644 --- a/docs/language/learn-ql/java/javadoc.rst +++ b/docs/language/learn-ql/java/javadoc.rst @@ -221,6 +221,6 @@ Currently, ``visibleIn`` only considers single-type imports, but you could exten Further reading --------------- -- Find out how you can use the location API to define queries on whitespace: :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. +- Find out how you can use the location API to define queries on whitespace: :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/java/source-locations.rst b/docs/language/learn-ql/java/source-locations.rst index 491a8b218f5..23c7c89cb74 100644 --- a/docs/language/learn-ql/java/source-locations.rst +++ b/docs/language/learn-ql/java/source-locations.rst @@ -1,7 +1,7 @@ Working with source locations ============================= -You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. +You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. About source locations ---------------------- @@ -186,5 +186,5 @@ Whitespace suggests that the programmer meant to toggle ``i`` between zero and o Further reading --------------- -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index 35d4df4dfb3..344e53f9951 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -1,5 +1,5 @@ -Types in Java -============= +Java types +========== You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues. @@ -299,6 +299,6 @@ Adding these three improvements, our final query becomes: Further reading --------------- -- Take a look at some of the other tutorials: :doc:`Tutorial: Expressions and statements `, :doc:`Tutorial: Navigating the call graph `, :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. +- Take a look at some of the other articles in this section: :doc:`Overflow-prone comparisons in Java `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. From e7b58571b65b6d9392bfde524c9af6ff438e5baa Mon Sep 17 00:00:00 2001 From: Alistair Christie Date: Mon, 2 Mar 2020 15:32:03 +0000 Subject: [PATCH 055/459] Make review comment changes --- docs/language/learn-ql/csharp/dataflow.rst | 2 +- .../learn-ql/csharp/introduce-libraries-csharp.rst | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/language/learn-ql/csharp/dataflow.rst b/docs/language/learn-ql/csharp/dataflow.rst index b60ab2e245d..22e939caf37 100644 --- a/docs/language/learn-ql/csharp/dataflow.rst +++ b/docs/language/learn-ql/csharp/dataflow.rst @@ -101,7 +101,7 @@ Unfortunately this will only give the expression in the argument, not the values and DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0))) select src -Then we can make the source more specific, for example an access to a public parameter. This query finds instances of a public parameter being used to open a file: +Then we can make the source more specific, for example an access to a public parameter. This query finds instances where a public parameter is used to open a file: .. code-block:: ql diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index c52695f92d3..b4f467a21bc 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1,12 +1,12 @@ -CodeQL library for C# -===================== +CodeQL libraries for C# +======================= -When you need to analyze a C# program, you can make use of the large collection of classes in the C# library for CodeQL. +When you're analyzing a C# program in {{ site.data.variables.product.prodname_dotcom }}, you can make use of the large collection of classes in the CodeQL libraries for C#. -About the C# library --------------------- +About the CodeQL libraries for C# +--------------------------------- -There is an extensive library for analyzing CodeQL databases extracted from C# projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``csharp.qll`` imports all the core C# library modules, so you can include the complete library by beginning your query with: +There is an extensive core library for analyzing CodeQL databases extracted from C# projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``csharp.qll`` imports all the core C# library modules, so you can include the complete library by beginning your query with: .. code-block:: ql From 162a683075997077339e565b7b8d1c360593dcb4 Mon Sep 17 00:00:00 2001 From: mchammer01 <42146119+mchammer01@users.noreply.github.com> Date: Thu, 5 Mar 2020 10:33:39 +0000 Subject: [PATCH 056/459] pre-migration task: update links --- .../learn-ql/javascript/dataflow-cheat-sheet.rst | 6 +++--- docs/language/learn-ql/javascript/dataflow.rst | 2 +- docs/language/learn-ql/javascript/flow-labels.rst | 4 ++-- .../learn-ql/javascript/introduce-libraries-js.rst | 2 +- .../learn-ql/javascript/introduce-libraries-ts.rst | 6 +++--- .../learn-ql/javascript/ql-for-javascript.rst | 12 ++++++------ docs/language/learn-ql/javascript/type-tracking.rst | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst index 27c7b196ee8..2fe9daa54dc 100644 --- a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst +++ b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst @@ -39,7 +39,7 @@ See also: `Global data flow `. +Use data flow nodes to match program elements independently of syntax. See also: :doc:`Analyzing data flow in JavaScript and TypeScript `. Predicates in the ``DataFlow::`` module: @@ -142,7 +142,7 @@ Files AST nodes --------- -See also: :doc:`AST class reference `. +See also: :doc:`Abstract syntax tree classes for JavaScript and TypeScript `. Conversion between DataFlow and AST nodes: @@ -163,7 +163,7 @@ String matching Type tracking ------------- -See also: :doc:`Type tracking tutorial `. +See also: :doc:`Using type tracking for API modeling `. Use the following template to define forward type tracking predicates: diff --git a/docs/language/learn-ql/javascript/dataflow.rst b/docs/language/learn-ql/javascript/dataflow.rst index 15cd1ad7e46..ed7905f93c2 100644 --- a/docs/language/learn-ql/javascript/dataflow.rst +++ b/docs/language/learn-ql/javascript/dataflow.rst @@ -470,7 +470,7 @@ What next? - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. -- Learn about writing more precise data-flow analyses in :doc:`Advanced data-flow analysis using flow labels ` +- Learn about writing more precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis ` Answers ------- diff --git a/docs/language/learn-ql/javascript/flow-labels.rst b/docs/language/learn-ql/javascript/flow-labels.rst index 2a2caee9040..8860f3dbd94 100644 --- a/docs/language/learn-ql/javascript/flow-labels.rst +++ b/docs/language/learn-ql/javascript/flow-labels.rst @@ -2,7 +2,7 @@ Using flow labels for precise data flow analysis ================================================ You can use basic inter-procedural data-flow analysis and taint tracking as described in -:doc:`Analyzing data flow in JavaScript/TypeScript ` to check whether there is a path in +:doc:`Analyzing data flow in JavaScript and TypeScript ` to check whether there is a path in the data-flow graph from some source node to a sink node that does not pass through any sanitizer nodes. Another way of thinking about this is that it statically models the flow of data through the program, and associates a flag with every data value telling us whether it might have come from a @@ -393,6 +393,6 @@ string may be an absolute path and whether it may contain ``..`` components. Further reading --------------- -- Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`Introducing the JavaScript libraries `. +- Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 8554694c97f..81ee048a6e8 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1031,6 +1031,6 @@ Predicate ``YAMLMapping.maps(key, value)`` models the key-value relation represe Further reading --------------- -- Learn about the standard CodeQL libraries used to write queries for TypeScript in :doc:`Introducing the TypeScript libraries `. +- Learn about the standard CodeQL libraries used to write queries for TypeScript in :doc:`CodeQL libraries for TypeScript `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index 9ec81a76bf1..a39cc379e0d 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -12,7 +12,7 @@ Support for analyzing TypeScript code is bundled with the CodeQL libraries for J import javascript -The :doc:`CodeQL library introduction for JavaScript ` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates. +The :doc:`CodeQL libraries for JavaScript ` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates. Syntax ------ @@ -136,7 +136,7 @@ The CodeQL class `ClassOrInterface `__. -Also see the documentation for classes in the `Introduction to the CodeQL libraries for JavaScript `__. +Also see the documentation for classes in the `CodeQL libraries for JavaScript `__. To select the type references to a class or an interface, use ``getTypeName()``. @@ -449,6 +449,6 @@ A `LocalNamespaceName `. +- Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. \ No newline at end of file diff --git a/docs/language/learn-ql/javascript/ql-for-javascript.rst b/docs/language/learn-ql/javascript/ql-for-javascript.rst index 476e43a6671..14c6439e105 100644 --- a/docs/language/learn-ql/javascript/ql-for-javascript.rst +++ b/docs/language/learn-ql/javascript/ql-for-javascript.rst @@ -19,17 +19,17 @@ These documents provide an overview of the CodeQL libraries for JavaScript and T - `Basic JavaScript query `__ describes how to write and run queries using LGTM. -- :doc:`Introducing the CodeQL libraries for JavaScript ` introduces the standard libraries used to write queries for JavaScript code. There is an extensive CodeQL library for analyzing JavaScript code. This tutorial briefly summarizes the most important classes and predicates provided by this library. +- :doc:`CodeQL libraries for JavaScript ` introduces the standard libraries used to write queries for JavaScript code. There is an extensive CodeQL library for analyzing JavaScript code. This tutorial briefly summarizes the most important classes and predicates provided by this library. -- :doc:`Introducing the CodeQL libraries for TypeScript ` introduces the standard libraries used to write queries for TypeScript code. +- :doc:`CodeQL libraries for TypeScript ` introduces the standard libraries used to write queries for TypeScript code. -- :doc:`Analyzing data flow in JavaScript/TypeScript ` demonstrates how to write queries using the standard data flow and taint tracking libraries for JavaScript/TypeScript. +- :doc:`Analyzing data flow in JavaScript and TypeScript ` demonstrates how to write queries using the standard data flow and taint tracking libraries for JavaScript/TypeScript. -- :doc:`Advanced data-flow analysis using flow labels ` shows a more advanced example of data flow analysis using flow labels. +- :doc:`Using flow labels for precise data flow analysis ` shows a more advanced example of data flow analysis using flow labels. -- :doc:`AST class reference ` gives an overview of all AST classes in the standard CodeQL library for JavaScript. +- :doc:`Abstract syntax tree classes for JavaScript and TypeScript ` gives an overview of all AST classes in the standard CodeQL library for JavaScript. -- :doc:`Data flow cheat sheet ` lists parts of the CodeQL libraries that are commonly used for variant analysis and in data flow queries. +- :doc:`Data flow cheat sheet for JavaScript ` lists parts of the CodeQL libraries that are commonly used for variant analysis and in data flow queries. Further reading --------------- diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index eace393c0ee..fe520e0a851 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -489,7 +489,7 @@ Prefer type tracking when: Prefer data-flow configurations when: - Tracking user-controlled data -- use `taint tracking `__. -- Differentiating between different kinds of user-controlled data -- use :doc:`flow labels `. +- Differentiating between different kinds of user-controlled data -- use :doc:`Using flow labels for precise data flow analysis `. - Tracking transformations of a value through generic utility functions. - Tracking values through string manipulation. - Generating a path from source to sink -- see :doc:`constructing path queries <../writing-queries/path-queries>`. @@ -522,4 +522,4 @@ What next? - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. -- Learn about writing precise data-flow analyses in :doc:`Advanced data-flow analysis using flow labels `. +- Learn about writing precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis `. From 0773bfc2d74b3c3e22c3c48cf8c4ccd81b78cecd Mon Sep 17 00:00:00 2001 From: mc <42146119+mchammer01@users.noreply.github.com> Date: Fri, 6 Mar 2020 08:17:52 +0000 Subject: [PATCH 057/459] Update docs/language/learn-ql/javascript/introduce-libraries-ts.rst Co-Authored-By: Felicity Chapman --- docs/language/learn-ql/javascript/introduce-libraries-ts.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index a39cc379e0d..d3d3eeb467c 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -12,7 +12,7 @@ Support for analyzing TypeScript code is bundled with the CodeQL libraries for J import javascript -The :doc:`CodeQL libraries for JavaScript ` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates. +:doc:`CodeQL libraries for JavaScript ` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates. Syntax ------ @@ -451,4 +451,4 @@ Further reading - Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. \ No newline at end of file +- Learn more about the query console in `Using the query console `__. From e0ceeef4dc76337e60b8eab8f5a05a0d88560b28 Mon Sep 17 00:00:00 2001 From: mc <42146119+mchammer01@users.noreply.github.com> Date: Fri, 6 Mar 2020 08:18:07 +0000 Subject: [PATCH 058/459] Update docs/language/learn-ql/javascript/type-tracking.rst Co-Authored-By: Felicity Chapman --- docs/language/learn-ql/javascript/type-tracking.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index fe520e0a851..f2e948ec65b 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -489,7 +489,7 @@ Prefer type tracking when: Prefer data-flow configurations when: - Tracking user-controlled data -- use `taint tracking `__. -- Differentiating between different kinds of user-controlled data -- use :doc:`Using flow labels for precise data flow analysis `. +- Differentiating between different kinds of user-controlled data -- see :doc:`Using flow labels for precise data flow analysis `. - Tracking transformations of a value through generic utility functions. - Tracking values through string manipulation. - Generating a path from source to sink -- see :doc:`constructing path queries <../writing-queries/path-queries>`. From fbe0735a5e71a05912a56575dae7ff636bdda5bc Mon Sep 17 00:00:00 2001 From: mchammer01 <42146119+mchammer01@users.noreply.github.com> Date: Fri, 6 Mar 2020 09:20:40 +0000 Subject: [PATCH 059/459] pre-migration tasks: address review comments --- docs/language/learn-ql/javascript/ast-class-reference.rst | 2 ++ docs/language/learn-ql/javascript/dataflow.rst | 7 +++---- docs/language/learn-ql/javascript/flow-labels.rst | 5 +++++ .../learn-ql/javascript/introduce-libraries-js.rst | 2 +- .../learn-ql/javascript/introduce-libraries-ts.rst | 2 +- docs/language/learn-ql/javascript/type-tracking.rst | 4 +++- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/language/learn-ql/javascript/ast-class-reference.rst b/docs/language/learn-ql/javascript/ast-class-reference.rst index 742ae5addb7..f0a7f88fc17 100644 --- a/docs/language/learn-ql/javascript/ast-class-reference.rst +++ b/docs/language/learn-ql/javascript/ast-class-reference.rst @@ -1,6 +1,8 @@ Abstract syntax tree classes for JavaScript and TypeScript ========================================================== +CodeQL has a large selection of classes for working with JavaScript and TypeScript statements and expressions. + Statement classes ----------------- diff --git a/docs/language/learn-ql/javascript/dataflow.rst b/docs/language/learn-ql/javascript/dataflow.rst index ed7905f93c2..f1ede8c3074 100644 --- a/docs/language/learn-ql/javascript/dataflow.rst +++ b/docs/language/learn-ql/javascript/dataflow.rst @@ -1,12 +1,11 @@ Analyzing data flow in JavaScript and TypeScript ================================================ +This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. + Overview -------- - -This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. - +The various sections in this article describe how to utilize the libraries for local data flow, global data flow, and taint tracking. As our running example, we will develop a query that identifies command-line arguments that are passed as a file path to the standard Node.js ``readFile`` function. While this is not a problematic pattern as such, it is typical of the kind of reasoning that is frequently used in security queries. diff --git a/docs/language/learn-ql/javascript/flow-labels.rst b/docs/language/learn-ql/javascript/flow-labels.rst index 8860f3dbd94..3970a26058b 100644 --- a/docs/language/learn-ql/javascript/flow-labels.rst +++ b/docs/language/learn-ql/javascript/flow-labels.rst @@ -1,6 +1,11 @@ Using flow labels for precise data flow analysis ================================================ +You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. + +Overview +-------- + You can use basic inter-procedural data-flow analysis and taint tracking as described in :doc:`Analyzing data flow in JavaScript and TypeScript ` to check whether there is a path in the data-flow graph from some source node to a sink node that does not pass through any sanitizer diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 81ee048a6e8..0e7b6a94ab6 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1,7 +1,7 @@ CodeQL libraries for JavaScript =============================== -This article is an overview of the extensive libraries you can use to analyze databases generated from JavaScript codebases. Using the libraries makes it easier for you to write queries. +You can use the extensive libraries described in this article to analyze databases generated from JavaScript codebases. Using these libraries makes it easier for you to write queries. Overview -------- diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index a39cc379e0d..35a47ee426b 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -1,7 +1,7 @@ CodeQL libraries for TypeScript =============================== -This article is an overview of the libraries you can use to analyze databases generated from TypeScript codebases. Using the libraries makes it easier for you to write queries. +You can use libraries to analyze databases generated from TypeScript codebases. Using these libraries makes it easier for you to write queries. Overview -------- diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index fe520e0a851..849205710b8 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -1,9 +1,11 @@ Using type tracking for API modeling ==================================== -This tutorial demonstrates how to build a simple model of the Firebase API +You can build a simple model of the Firebase API using the CodeQL type-tracking library for JavaScript. +Overview +-------- The type-tracking library makes it possible to track values through properties and function calls, usually to recognize method calls and properties accessed on a specific type of object. From d777c08fc285a4da045523a3c0ad7f350d77b030 Mon Sep 17 00:00:00 2001 From: mc <42146119+mchammer01@users.noreply.github.com> Date: Fri, 6 Mar 2020 10:50:59 +0000 Subject: [PATCH 060/459] Update docs/language/learn-ql/javascript/type-tracking.rst Co-Authored-By: Felicity Chapman --- docs/language/learn-ql/javascript/type-tracking.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index 46344454df9..da8378a8e71 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -1,7 +1,7 @@ Using type tracking for API modeling ==================================== -You can build a simple model of the Firebase API +You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. Overview From 3558bb8bc048a58da65209e1045dbcd1cee49f78 Mon Sep 17 00:00:00 2001 From: mc <42146119+mchammer01@users.noreply.github.com> Date: Fri, 6 Mar 2020 10:51:13 +0000 Subject: [PATCH 061/459] Update docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst Co-Authored-By: Felicity Chapman --- docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst index 2fe9daa54dc..b87c1062317 100644 --- a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst +++ b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst @@ -1,7 +1,7 @@ Data flow cheat sheet for JavaScript ==================================== -This page describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries. +This article describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries. Taint tracking path queries --------------------------- From 90a9a6d2ac0fd0cc2f2860e1c04aee137f9facc0 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 6 Mar 2020 15:13:10 +0000 Subject: [PATCH 062/459] Update docs/language/learn-ql/python/introduce-libraries-python.rst --- docs/language/learn-ql/python/introduce-libraries-python.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 80944b852a2..81889a0cb94 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -154,7 +154,7 @@ Both forms are equivalent. Using the positive expression, the whole query looks ➤ `See this in the query console `__. Many projects include pass-only ``except`` blocks. Summary -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^ The most commonly used standard classes in the syntactic part of the library are organized as follows: From bbeefd57470aef797172cfec18aa11f5af97add8 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 9 Mar 2020 19:21:31 -0700 Subject: [PATCH 063/459] Python: Modernizes query --- python/ql/src/Functions/SignatureOverriddenMethod.ql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/Functions/SignatureOverriddenMethod.ql b/python/ql/src/Functions/SignatureOverriddenMethod.ql index 47182d8d87d..a2971d2a033 100644 --- a/python/ql/src/Functions/SignatureOverriddenMethod.ql +++ b/python/ql/src/Functions/SignatureOverriddenMethod.ql @@ -15,17 +15,17 @@ import python import Expressions.CallArgs -from FunctionObject base, PyFunctionObject derived +from FunctionValue base, PythonFunctionValue derived where not exists(base.getACall()) and - not exists(FunctionObject a_derived | + not exists(FunctionValue a_derived | a_derived.overrides(base) and exists(a_derived.getACall()) ) and - not derived.getFunction().isSpecialMethod() and + not derived.getScope().isSpecialMethod() and derived.getName() != "__init__" and derived.isNormalMethod() and - not derived.getFunction().isSpecialMethod() and + not derived.getScope().isSpecialMethod() and // call to overrides distributed for efficiency ( (derived.overrides(base) and derived.minParameters() > base.maxParameters()) From 7ce905a310827ca2b8477f1068f293e9a582f1d3 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Mon, 9 Mar 2020 19:29:47 -0700 Subject: [PATCH 064/459] Python: Adds preliminary modernization --- python/ql/src/Functions/ReturnValueIgnored.ql | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index 19896533a7c..e3b1ccd1dbe 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -21,9 +21,9 @@ predicate meaningful_return_value(Expr val) { or val instanceof BooleanLiteral or - exists(FunctionObject callee | val = callee.getACall().getNode() and returns_meaningful_value(callee)) + exists(FunctionValue callee | val = callee.getACall().getNode() and returns_meaningful_value(callee)) or - not exists(FunctionObject callee | val = callee.getACall().getNode()) and not val instanceof Name + not exists(FunctionValue callee | val = callee.getACall().getNode()) and not val instanceof Name } /* Value is used before returning, and thus its value is not lost if ignored */ @@ -31,18 +31,18 @@ predicate used_value(Expr val) { exists(LocalVariable var, Expr other | var.getAnAccess() = val and other = var.getAnAccess() and not other = val) } -predicate returns_meaningful_value(FunctionObject f) { - not exists(f.getFunction().getFallthroughNode()) +predicate returns_meaningful_value(FunctionValue f) { + not exists(f.getScope().getFallthroughNode()) and ( - exists(Return ret, Expr val | ret.getScope() = f.getFunction() and val = ret.getValue() | + exists(Return ret, Expr val | ret.getScope() = f.getScope() and val = ret.getValue() | meaningful_return_value(val) and not used_value(val) ) or /* Is f a builtin function that returns something other than None? * Ignore __import__ as it is often called purely for side effects */ - f.isC() and f.getAnInferredReturnType() != theNoneType() and not f.getName() = "__import__" + f.isBuiltin() and f.getAnInferredReturnType() != theNoneType() and not f.getName() = "__import__" ) } @@ -55,7 +55,7 @@ predicate wrapped_in_try_except(ExprStmt call) { ) } -from ExprStmt call, FunctionObject callee, float percentage_used, int total +from ExprStmt call, FunctionValue callee, float percentage_used, int total where call.getValue() = callee.getACall().getNode() and returns_meaningful_value(callee) and not wrapped_in_try_except(call) and exists(int unused | From e97c72cd5d907183447b38877182194a11d2fdb0 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 10 Mar 2020 11:34:09 +0100 Subject: [PATCH 065/459] Dataflow: Adjust imports. --- .../code/cpp/dataflow/internal/DataFlowImplConsistency.qll | 3 ++- .../code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll | 3 ++- .../code/csharp/dataflow/internal/DataFlowImplConsistency.qll | 3 ++- .../code/java/dataflow/internal/DataFlowImplConsistency.qll | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll index 45f2a5784b8..60130a1aea9 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -5,7 +5,8 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public -private import TaintTrackingUtil +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public module Consistency { private class RelevantNode extends Node { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll index 45f2a5784b8..60130a1aea9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -5,7 +5,8 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public -private import TaintTrackingUtil +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public module Consistency { private class RelevantNode extends Node { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll index 45f2a5784b8..60130a1aea9 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -5,7 +5,8 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public -private import TaintTrackingUtil +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public module Consistency { private class RelevantNode extends Node { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index 45f2a5784b8..60130a1aea9 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -5,7 +5,8 @@ private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public -private import TaintTrackingUtil +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public module Consistency { private class RelevantNode extends Node { From b1a24705ad71d3eed68fbcd8a42ea539e49d47b4 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Tue, 10 Mar 2020 09:26:28 +0000 Subject: [PATCH 066/459] Apply suggestions from code review Co-Authored-By: Felicity Chapman Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/cpp/guards.rst | 2 +- .../learn-ql/cpp/introduce-libraries-cpp.rst | 14 +++++--------- .../learn-ql/cpp/private-field-initialization.rst | 4 ++-- .../learn-ql/cpp/value-numbering-hash-cons.rst | 3 +-- .../learn-ql/cpp/zero-space-terminator.rst | 2 +- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/docs/language/learn-ql/cpp/guards.rst b/docs/language/learn-ql/cpp/guards.rst index 35f185b8b49..409df0a8f81 100644 --- a/docs/language/learn-ql/cpp/guards.rst +++ b/docs/language/learn-ql/cpp/guards.rst @@ -1,7 +1,7 @@ Using the guards library in C and C++ ===================================== -You can use the CodeQL guards library to identify conditional expressions that control the execution of other code in C and C++ codebases. +You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases. About the guards library ------------------------ diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 2985bc24a67..63cd93a0a82 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -1,10 +1,10 @@ -CodeQL libraries for C and C++ -============================== +CodeQL library for C and C++ +============================ -Explore the standard CodeQL libraries for C and C++. +When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++. -About the CodeQL libraries for C and C++ ----------------------------------------- +About the CodeQL library for C and C++ +-------------------------------------- There is an extensive library for analyzing CodeQL databases extracted from C/C++ projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``cpp.qll`` imports all the core C/C++ library modules, so you can include the complete library by beginning your query with: @@ -15,10 +15,6 @@ The library is implemented as a set of QL modules, that is, files with the exten The rest of this topic summarizes the available CodeQL classes and corresponding C/C++ constructs. -.. pull-quote:: Note - - You can find related classes and features using the query console's auto-complete feature. You can also press *F3* to jump to the definition of any element. Library files are opened in new tabs in the console. - Commonly-used library classes ------------------------------ diff --git a/docs/language/learn-ql/cpp/private-field-initialization.rst b/docs/language/learn-ql/cpp/private-field-initialization.rst index f7bc180cd4b..852f982daa2 100644 --- a/docs/language/learn-ql/cpp/private-field-initialization.rst +++ b/docs/language/learn-ql/cpp/private-field-initialization.rst @@ -1,7 +1,7 @@ Refining a query to account for edge cases ========================================== -You can improve the results generated by a CodeQL query by adding conditions to remove false positives caused by common edge cases. +You can improve the results generated by a CodeQL query by adding conditions to remove false positive results caused by common edge cases. Overview -------- @@ -126,7 +126,7 @@ This case can be excluded by creating a recursive predicate. The recursive predi Refinement 4—simplifying the query ---------------------------------- -Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see `transitive closures `__ in the QL language handbook. +Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see `Transitive closures `__ in the QL language handbook. .. code-block:: ql diff --git a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst index c4b16bcfd57..de102a15f6d 100644 --- a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst +++ b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst @@ -8,7 +8,7 @@ About the hash consing and value numbering libraries In C and C++ databases, each node in the abstract syntax tree is represented by a separate object. This allows both analysis and results display to refer to specific appearances of a piece of syntax. However, it is frequently useful to determine whether two expressions are equivalent, either syntactically or semantically. -The hash consing library (defined in ``semmle.code.cpp.valuenumbering.HashCons``) provides a mechanism for identifying expressions that have the same syntactic structure. The global value numbering library (defined in ``semmle.code.cpp.valuenumbering.GlobalValueNumbering``) provides a mechanism for identifying expressions that compute the same value at runtime. Both libraries partition the expressions in each function into equivalence classes represented by objects. Each ``HashCons`` object represents a set of expressions with identical parse trees, while ``GVN`` objects represent sets of expressions that will always compute the same value. For more information, see `hash consing `__ and `value numbering `__ on Wikipedia. +The hash consing library (defined in ``semmle.code.cpp.valuenumbering.HashCons``) provides a mechanism for identifying expressions that have the same syntactic structure. The global value numbering library (defined in ``semmle.code.cpp.valuenumbering.GlobalValueNumbering``) provides a mechanism for identifying expressions that compute the same value at runtime. Both libraries partition the expressions in each function into equivalence classes represented by objects. Each ``HashCons`` object represents a set of expressions with identical parse trees, while ``GVN`` objects represent sets of expressions that will always compute the same value. For more information, see `Hash consing `__ and `Value numbering `__ on Wikipedia. Example C code -------------- @@ -110,4 +110,3 @@ Example query hashCons(outer.getCondition()) = hashCons(inner.getCondition()) select inner.getCondition(), "The condition of this if statement duplicates the condition of $@", outer.getCondition(), "an enclosing if statement" - diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index 4611559f204..c6e2a557aaa 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -100,7 +100,7 @@ When you have defined the basic query then you can refine the query to include f Improving the query using the 'SSA' library ------------------------------------------- -The ``SSA`` library represents variables in static single assignment (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. For more information, see `static single assignment `__ on Wikipedia. +The ``SSA`` library represents variables in static single assignment (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. For more information, see `Static single assignment `__ on Wikipedia. Including examples where the string size is stored before use ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 6017197870c1eecdb9d326d4061a60d1f4006625 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 10 Mar 2020 08:08:05 -0700 Subject: [PATCH 067/459] Python: Autoformats --- python/ql/src/Functions/SignatureOverriddenMethod.ql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/src/Functions/SignatureOverriddenMethod.ql b/python/ql/src/Functions/SignatureOverriddenMethod.ql index a2971d2a033..e695f2385ea 100644 --- a/python/ql/src/Functions/SignatureOverriddenMethod.ql +++ b/python/ql/src/Functions/SignatureOverriddenMethod.ql @@ -6,7 +6,6 @@ * @problem.severity warning * @tags reliability * correctness - * @problem.severity warning * @sub-severity high * @precision very-high * @id py/inheritance/signature-mismatch @@ -19,8 +18,8 @@ from FunctionValue base, PythonFunctionValue derived where not exists(base.getACall()) and not exists(FunctionValue a_derived | - a_derived.overrides(base) and - exists(a_derived.getACall()) + a_derived.overrides(base) and + exists(a_derived.getACall()) ) and not derived.getScope().isSpecialMethod() and derived.getName() != "__init__" and @@ -28,8 +27,9 @@ where not derived.getScope().isSpecialMethod() and // call to overrides distributed for efficiency ( - (derived.overrides(base) and derived.minParameters() > base.maxParameters()) + derived.overrides(base) and derived.minParameters() > base.maxParameters() or - (derived.overrides(base) and derived.maxParameters() < base.minParameters()) + derived.overrides(base) and derived.maxParameters() < base.minParameters() ) -select derived, "Overriding method '" + derived.getName() + "' has signature mismatch with $@.", base, "overridden method" +select derived, "Overriding method '" + derived.getName() + "' has signature mismatch with $@.", + base, "overridden method" From 160f6cbc1527b2f61cedb460537c38be54dfb7fe Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 10 Mar 2020 08:51:20 -0700 Subject: [PATCH 068/459] Python: Adds preliminary modernization --- python/ql/src/Functions/IterReturnsNonSelf.ql | 6 ++--- .../src/semmle/python/objects/ObjectAPI.qll | 22 ++++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/python/ql/src/Functions/IterReturnsNonSelf.ql b/python/ql/src/Functions/IterReturnsNonSelf.ql index 0899cf798a1..c10eaf74c39 100644 --- a/python/ql/src/Functions/IterReturnsNonSelf.ql +++ b/python/ql/src/Functions/IterReturnsNonSelf.ql @@ -12,8 +12,8 @@ import python -Function iter_method(ClassObject t) { - result = ((FunctionObject)t.lookupAttribute("__iter__")).getFunction() +Function iter_method(ClassValue t) { + result = ((FunctionValue)t.lookup("__iter__")).getScope() } predicate is_self(Name value, Function f) { @@ -28,6 +28,6 @@ predicate returns_non_self(Function f) { exists(Return r | r.getScope() = f and not exists(r.getValue())) } -from ClassObject t, Function iter +from ClassValue t, Function iter where t.isIterator() and iter = iter_method(t) and returns_non_self(iter) select t, "Class " + t.getName() + " is an iterator but its $@ method does not return 'self'.", iter, iter.getName() \ No newline at end of file diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 587a569e0f7..e467bb2aa0b 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -374,7 +374,7 @@ class CallableValue extends Value { /** Class representing classes in the Python program, both Python and built-in. */ -class ClassValue extends Value { +class ClassValue extends Value { ClassValue() { this.(ObjectInternal).isClass() = true @@ -413,6 +413,26 @@ class ClassValue extends Value { this.hasAttribute("__getitem__") } + /** Holds if this class is an iterator. */ + predicate isIterator() { + this.hasAttribute("__iter__") and + (major_version() = 3 and this.hasAttribute("__next__") + or + /* Because 'next' is a common method name we need to check that an __iter__ + * method actually returns this class. This is not needed for Py3 as the + * '__next__' method exists to define a class as an iterator. + */ + major_version() = 2 and this.hasAttribute("next") and + exists(ClassObject other, FunctionObject iter | + other.declaredAttribute("__iter__") = iter | + iter.getAnInferredReturnType() = this + ) + ) + or + /* This will be redundant when we have C class information */ + this = ClassValue::generator() + } + /** Holds if this class is a descriptor. */ predicate isDescriptorType() { this.hasAttribute("__get__") From f1238f1ec92e87a68ef3a6bf0fb121aadc4ae0c0 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Tue, 10 Mar 2020 17:11:59 +0000 Subject: [PATCH 069/459] Update docs/language/learn-ql/python/introduce-libraries-python.rst --- docs/language/learn-ql/python/introduce-libraries-python.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 81889a0cb94..c7809eb710b 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -1,7 +1,7 @@ CodeQL library for Python ========================= -When you need to analyze a Python program, you can make use of the large collection of classes in the Python library for CodeQL. +When you need to analyze a Python program, you can make use of the large collection of classes in the CodeQL library for Python. About the CodeQL library for Python ----------------------------------- From ba8ebe9f3a7db12a086df40b3ebbe7d69143fcf9 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 10 Mar 2020 11:41:59 -0700 Subject: [PATCH 070/459] C++: accept test changes --- cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected | 2 +- .../test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected | 2 +- cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected | 2 +- .../test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index bcaa0ab3f25..f44773f0fd3 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -1276,7 +1276,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_9 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_12(void) = ReturnIndirection : &:r268_8, ~m270_11 +# 268| v268_12(void) = ReturnIndirection[s] : &:r268_8, ~m270_11 # 268| r268_13(glval) = VariableAddress[#return] : # 268| v268_14(void) = ReturnValue : &:r268_13, m271_4 # 268| v268_15(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index 07d0c8ea717..cb15cebf59c 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1271,7 +1271,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_9 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_12(void) = ReturnIndirection : &:r268_8, m268_9 +# 268| v268_12(void) = ReturnIndirection[s] : &:r268_8, m268_9 # 268| r268_13(glval) = VariableAddress[#return] : # 268| v268_14(void) = ReturnValue : &:r268_13, m271_4 # 268| v268_15(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 824799db812..f08858d1a9c 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -1182,7 +1182,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_8 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4 +# 268| v268_11(void) = ReturnIndirection[s] : &:r268_7, ~mu268_4 # 268| r268_12(glval) = VariableAddress[#return] : # 268| v268_13(void) = ReturnValue : &:r268_12, m271_4 # 268| v268_14(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index 824799db812..f08858d1a9c 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -1182,7 +1182,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_8 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4 +# 268| v268_11(void) = ReturnIndirection[s] : &:r268_7, ~mu268_4 # 268| r268_12(glval) = VariableAddress[#return] : # 268| v268_13(void) = ReturnValue : &:r268_12, m271_4 # 268| v268_14(void) = UnmodeledUse : mu* From 43347d006c62d788c5ebe07387bc40c6e4c238a1 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 01:32:30 +0000 Subject: [PATCH 071/459] Combine and rename first detective tutorial --- .../learn-ql/beginner/find-the-thief.rst | 295 ++++++++++++++++++ .../learn-ql/beginner/find-thief-1.rst | 71 ----- .../learn-ql/beginner/find-thief-2.rst | 141 --------- .../learn-ql/beginner/find-thief-3.rst | 80 ----- docs/language/learn-ql/beginner/heir.rst | 2 +- .../learn-ql/beginner/ql-tutorials.rst | 2 +- 6 files changed, 297 insertions(+), 294 deletions(-) create mode 100644 docs/language/learn-ql/beginner/find-the-thief.rst delete mode 100644 docs/language/learn-ql/beginner/find-thief-1.rst delete mode 100644 docs/language/learn-ql/beginner/find-thief-2.rst delete mode 100644 docs/language/learn-ql/beginner/find-thief-3.rst diff --git a/docs/language/learn-ql/beginner/find-the-thief.rst b/docs/language/learn-ql/beginner/find-the-thief.rst new file mode 100644 index 00000000000..cee0a87943c --- /dev/null +++ b/docs/language/learn-ql/beginner/find-the-thief.rst @@ -0,0 +1,295 @@ +Find the thief +============== + +Introduction +------------ + +There is a small village hidden away in the mountains. The village is divided into four parts—north, south, east, and west—and in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown! + +You know that the thief must live in the village, since nobody else knew about the crown. After some expert detective work, you obtain a list of all the people in the village and some of their personal details. + ++------+-----+------------+--------+----------+ +| Name | Age | Hair color | Height | Location | ++======+=====+============+========+==========+ +| ... | ... | ... | ... | ... | ++------+-----+------------+--------+----------+ + +Sadly, you still have no idea who could have stolen the crown so you walk around the village to find clues. The villagers act very suspiciously and you are convinced they have information about the thief. They refuse to share their knowledge with you directly, but they reluctantly agree to answer questions. They are still not very talkative and **only answer questions with 'yes' or 'no'**. + +You start asking some creative questions and making notes of the answers so you can compare them with your information later: + ++------+--------------------------------------------------------------------+--------+ +| | Question | Answer | ++======+====================================================================+========+ +| (1) | Is the thief taller than 150 cm? | yes | ++------+--------------------------------------------------------------------+--------+ +| (2) | Does the thief have blond hair? | no | ++------+--------------------------------------------------------------------+--------+ +| (3) | Is the thief bald? | no | ++------+--------------------------------------------------------------------+--------+ +| (4) | Is the thief younger than 30? | no | ++------+--------------------------------------------------------------------+--------+ +| (5) | Does the thief live east of the castle? | yes | ++------+--------------------------------------------------------------------+--------+ +| (6) | Does the thief have black or brown hair? | yes | ++------+--------------------------------------------------------------------+--------+ +| (7) | Is the thief taller than 180cm and shorter than 190cm? | no | ++------+--------------------------------------------------------------------+--------+ +| (8) | Is the thief the tallest person in the village? | no | ++------+--------------------------------------------------------------------+--------+ +| (9) | Is the thief shorter than the average villager? | yes | ++------+--------------------------------------------------------------------+--------+ +| (10) | Is the thief the oldest person in the eastern part of the village? | yes | ++------+--------------------------------------------------------------------+--------+ + +There is too much information to search through by hand, so you decide to use your newly acquired QL skills to help you with your investigation... + +#. Open the `query console `__ to get started. +#. Select a language and a demo project. For this tutorial, any language and project will do. +#. Delete the default code ``import select "hello world"``. + +QL libraries +------------ + +We've defined a number of QL `predicates `__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age. + ++--------------------+----------------------------------------------------------------------------------------+ +| Predicate | Description | ++====================+========================================================================================+ +| ``getAge()`` | returns the age of the person (in years) as an ``int`` | ++--------------------+----------------------------------------------------------------------------------------+ +| ``getHairColor()`` | returns the hair color of the person as a ``string`` | ++--------------------+----------------------------------------------------------------------------------------+ +| ``getHeight()`` | returns the height of the person (in cm) as a ``float`` | ++--------------------+----------------------------------------------------------------------------------------+ +| ``getLocation()`` | returns the location of the person's home (north, south, east or west) as a ``string`` | ++--------------------+----------------------------------------------------------------------------------------+ + +We've stored these predicates in the QL library ``tutorial.qll``. To access this library, type ``import tutorial`` in the query console. + +Libraries are convenient for storing commonly used predicates. This saves you from defining a predicate every time you need it. Instead you can just ``import`` the library and use the predicate directly. Once you have imported the library, you can apply any of these predicates to an expression by appending it. + +For example, ``t.getHeight()`` applies ``getHeight()`` to ``t`` and returns the height of ``t``. + +Start the search +----------------- + +The villagers answered "yes" to the question "Is the thief taller than 150cm?" To use this information, you can write the following query to list all villagers taller than 150cm. These are all possible suspects. + +.. code-block:: ql + + from Person t + where t.getHeight() > 150 + select t + +The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type `__ of ``t`` is ``Person``. + +Before you use the rest of your answers in your QL search, here are some more tools and examples to help you write your own QL queries: + +Logical connectives +------------------- + +Using `logical connectives `__, you can write more complex queries that combine different pieces of information. + +For example, if you know that the thief is older than 30 *and* has brown hair, you can use the following ``where`` clause to link two predicates: + +.. code-block:: ql + + where t.getAge() > 30 and t.getHairColor() = "brown" + +.. pull-quote:: + + Note + + The predicate ``getHairColor()`` returns a ``string``, so we need to include quotation marks around the result ``"brown"``. + +If the thief does *not* live north of the castle, you can use: + +.. code-block:: ql + + where not t.getLocation() = "north" + +If the thief has brown hair *or* black hair, you can use: + +.. code-block:: ql + + where t.getHairColor() = "brown" or t.getHairColor() = "black" + +You can also combine these connectives into longer statements: + +.. code-block:: ql + + where t.getAge() > 30 + and (t.getHairColor() = "brown" or t.getHairColor() = "black") + and not t.getLocation() = "north" + +.. pull-quote:: + + Note + + We've placed parentheses around the ``or`` clause to make sure that the query is evaluated as intended. Without parentheses, the connective ``and`` takes precedence over ``or``. + +Predicates don't always return exactly one value. For example, if a person ``p`` has black hair which is turning gray, ``p.getHairColor()`` will return two values: black and gray. + +What if the thief is bald? In that case, the thief has no hair, so the ``getHairColor()`` predicate simply doesn't return any results! + +If you know that the thief definitely isn't bald, then there must be a color that matches the thief's hair color. One way to express this in QL is to introduce a new variable ``c`` of type ``string`` and select those ``t`` where ``t.getHairColor()`` matches a value of ``c``. + +.. code-block:: ql + + from Person t, string c + where t.getHairColor() = c + select t + +Notice that we have only temporarily introduced the variable ``c`` and we didn't need it at all in the ``select`` clause. In this case, it is better to use ``exists``: + +.. code-block:: ql + + from Person t + where exists(string c | t.getHairColor() = c) + select t + +``exists`` introduces a temporary variable ``c`` of type ``string`` and holds only if there is at least one ``string c`` that satisfies ``t.getHairColor() = c``. + +.. pull-quote:: + + Note + + If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier `__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``. + +The real investigation +---------------------- + +You are now ready to track down the thief! Using the examples above, write a query to find the people who satisfy the answers to the first eight questions: + ++---+--------------------------------------------------------+--------+ +| | Question | Answer | ++===+========================================================+========+ +| 1 | Is the thief taller than 150 cm? | yes | ++---+--------------------------------------------------------+--------+ +| 2 | Does the thief have blond hair? | no | ++---+--------------------------------------------------------+--------+ +| 3 | Is the thief bald? | no | ++---+--------------------------------------------------------+--------+ +| 4 | Is the thief younger than 30? | no | ++---+--------------------------------------------------------+--------+ +| 5 | Does the thief live east of the castle? | yes | ++---+--------------------------------------------------------+--------+ +| 6 | Does the thief have black or brown hair? | yes | ++---+--------------------------------------------------------+--------+ +| 7 | Is the thief taller than 180cm and shorter than 190cm? | no | ++---+--------------------------------------------------------+--------+ +| 8 | Is the thief the oldest person in the village? | no | ++---+--------------------------------------------------------+--------+ + +Hints +^^^^^ + +#. Don't forget to ``import tutorial``! +#. Translate each question into QL separately. Look at the examples above if you get stuck. +#. For question 3, remember that a bald person does not have a hair color. +#. For question 8, note that if a person is *not* the oldest, then there is at least one person who is older than them. +#. Combine the conditions using logical connectives to get a query of the form: + +.. code-block:: ql + + import tutorial + + from Person t + where and + not and + ... + select t + +Once you have finished, you will have a list of possible suspects. One of those people must be the thief! + +➤ `See the answer in the query console `__ + +.. pull-quote:: + + Note + + In the answer, we used ``/*`` and ``*/`` to label the different parts of the query. Any text surrounded by ``/*`` and ``*/`` is not evaluated as part of the QL code, but is just a *comment*. + +You are getting closer to solving the mystery! Unfortunately, you still have quite a long list of suspects... To find out which of your suspects is the thief, you must gather more information and refine your query in the next step. + +More advanced queries +--------------------- + +What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates `__. + +In general, an aggregate is a function that performs an operation on multiple pieces of data and returns a single value as its output. Common aggregates are ``count``, ``max``, ``min``, ``avg`` (average) and ``sum``. The general way to use an aggregate is: + +.. code-block:: ql + + ( | | ) + +For example, you can use the ``max`` aggregate to find the age of the oldest person in the village: + +.. code-block:: ql + + max(int i | exists(Person p | p.getAge() = i) | i) + +This aggregate considers all integers ``i``, limits ``i`` to values that match the ages of people in the village, and then returns the largest matching integer. + +But how can you use this in an actual query? + +If the thief is the oldest person in the village, then you know that the thief's age is equal to the maximum age of the villagers: + +.. code-block:: ql + + from Person t + where t.getAge() = max(int i | exists(Person p | p.getAge() = i) | i) + select t + +This general aggregate syntax is quite long and inconvenient. In most cases, you can omit certain parts of the aggregate. A particularly helpful QL feature is *ordered aggregation*. This allows you to order the expression using ``order by``. + +For example, selecting the oldest villager becomes much simpler if you use an ordered aggregate. + +.. code-block:: ql + + select max(Person p | | p order by p.getAge()) + +The ordered aggregate considers every person ``p`` and selects the person with the maximum age. In this case, there are no restrictions on what people to consider, so the ```` clause is empty. Note that if there are several people with the same maximum age, the query lists all of them. + +Here are some more examples of aggregates: + ++-------------------------------------------------------------------------+---------------------------------------------------+ +| Example | Result | ++=========================================================================+===================================================+ +| ``min(Person p | p.getLocation() = "east" | p order by p.getHeight())`` | shortest person in the east of the village | ++-------------------------------------------------------------------------+---------------------------------------------------+ +| ``count(Person p | p.getLocation() = "south" | p)`` | number of people in the south of the village | ++-------------------------------------------------------------------------+---------------------------------------------------+ +| ``avg(Person p | | p.getHeight())`` | average height of the villagers | ++-------------------------------------------------------------------------+---------------------------------------------------+ +| ``sum(Person p | p.getHairColor() = "brown" | p.getAge())`` | combined age of all the villagers with brown hair | ++-------------------------------------------------------------------------+---------------------------------------------------+ + +Capture the culprit +------------------- + +You can now translate the remaining questions into QL: + ++-----+--------------------------------------------------------------------+--------+ +| | Question | Answer | ++=====+====================================================================+========+ +| ... | ... | ... | ++-----+--------------------------------------------------------------------+--------+ +| 9 | Is the thief the tallest person in the village? | no | ++-----+--------------------------------------------------------------------+--------+ +| 10 | Is the thief shorter than the average villager? | yes | ++-----+--------------------------------------------------------------------+--------+ +| 11 | Is the thief the oldest person in the eastern part of the village? | yes | ++-----+--------------------------------------------------------------------+--------+ + +Have you found the thief? + +➤ `See the answer in the query console `__ + +What next? +---------- + +- Help the villagers track down another criminal in the :doc:`next tutorial `. +- Find out more about the concepts you discovered in this tutorial in the `QL language handbook `__. +- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/find-thief-1.rst b/docs/language/learn-ql/beginner/find-thief-1.rst deleted file mode 100644 index 3df6c108837..00000000000 --- a/docs/language/learn-ql/beginner/find-thief-1.rst +++ /dev/null @@ -1,71 +0,0 @@ -Find the thief: Introduction -============================ - -There is a small village hidden away in the mountains. The village is divided into four parts—north, south, east, and west—and in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown! - -You know that the thief must live in the village, since nobody else knew about the crown. After some expert detective work, you obtain a list of all the people in the village and some of their personal details. - -+------+-----+------------+--------+----------+ -| Name | Age | Hair color | Height | Location | -+======+=====+============+========+==========+ -| ... | ... | ... | ... | ... | -+------+-----+------------+--------+----------+ - -Sadly, you still have no idea who could have stolen the crown so you walk around the village to find clues. The villagers act very suspiciously and you are convinced they have information about the thief. They refuse to share their knowledge with you directly, but they reluctantly agree to answer questions. They are still not very talkative and **only answer questions with 'yes' or 'no'**. - -You start asking some creative questions and making notes of the answers so you can compare them with your information later: - -+------+--------------------------------------------------------------------+--------+ -| | Question | Answer | -+======+====================================================================+========+ -| (1) | Is the thief taller than 150 cm? | yes | -+------+--------------------------------------------------------------------+--------+ -| (2) | Does the thief have blond hair? | no | -+------+--------------------------------------------------------------------+--------+ -| (3) | Is the thief bald? | no | -+------+--------------------------------------------------------------------+--------+ -| (4) | Is the thief younger than 30? | no | -+------+--------------------------------------------------------------------+--------+ -| (5) | Does the thief live east of the castle? | yes | -+------+--------------------------------------------------------------------+--------+ -| (6) | Does the thief have black or brown hair? | yes | -+------+--------------------------------------------------------------------+--------+ -| (7) | Is the thief taller than 180cm and shorter than 190cm? | no | -+------+--------------------------------------------------------------------+--------+ -| (8) | Is the thief the tallest person in the village? | no | -+------+--------------------------------------------------------------------+--------+ -| (9) | Is the thief shorter than the average villager? | yes | -+------+--------------------------------------------------------------------+--------+ -| (10) | Is the thief the oldest person in the eastern part of the village? | yes | -+------+--------------------------------------------------------------------+--------+ - -There is too much information to search through by hand, so you decide to use your newly acquired QL skills to help you with your investigation... - -#. Open the `query console `__ to get started. -#. Select a language and a demo project. For this tutorial, any language and project will do. -#. Delete the default code ``import select "hello world"``. - -QL libraries ------------- - -We've defined a number of QL `predicates `__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age. - -+--------------------+----------------------------------------------------------------------------------------+ -| Predicate | Description | -+====================+========================================================================================+ -| ``getAge()`` | returns the age of the person (in years) as an ``int`` | -+--------------------+----------------------------------------------------------------------------------------+ -| ``getHairColor()`` | returns the hair color of the person as a ``string`` | -+--------------------+----------------------------------------------------------------------------------------+ -| ``getHeight()`` | returns the height of the person (in cm) as a ``float`` | -+--------------------+----------------------------------------------------------------------------------------+ -| ``getLocation()`` | returns the location of the person's home (north, south, east or west) as a ``string`` | -+--------------------+----------------------------------------------------------------------------------------+ - -We've stored these predicates in the QL library ``tutorial.qll``. To access this library, type ``import tutorial`` in the query console. - -Libraries are convenient for storing commonly used predicates. This saves you from defining a predicate every time you need it. Instead you can just ``import`` the library and use the predicate directly. Once you have imported the library, you can apply any of these predicates to an expression by appending it. - -For example, ``t.getHeight()`` applies ``getHeight()`` to ``t`` and returns the height of ``t``. - -Continue to the next page to :doc:`start the investigation `. diff --git a/docs/language/learn-ql/beginner/find-thief-2.rst b/docs/language/learn-ql/beginner/find-thief-2.rst deleted file mode 100644 index b31f978d36a..00000000000 --- a/docs/language/learn-ql/beginner/find-thief-2.rst +++ /dev/null @@ -1,141 +0,0 @@ -Find the thief: Start the search -================================ - -The villagers answered "yes" to the question "Is the thief taller than 150cm?" To use this information, you can write the following query to list all villagers taller than 150cm. These are all possible suspects. - -.. code-block:: ql - - from Person t - where t.getHeight() > 150 - select t - -The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type `__ of ``t`` is ``Person``. - -Before you use the rest of your answers in your QL search, here are some more tools and examples to help you write your own QL queries: - -Logical connectives -------------------- - -Using `logical connectives `__, you can write more complex queries that combine different pieces of information. - -For example, if you know that the thief is older than 30 *and* has brown hair, you can use the following ``where`` clause to link two predicates: - -.. code-block:: ql - - where t.getAge() > 30 and t.getHairColor() = "brown" - -.. pull-quote:: - - Note - - The predicate ``getHairColor()`` returns a ``string``, so we need to include quotation marks around the result ``"brown"``. - -If the thief does *not* live north of the castle, you can use: - -.. code-block:: ql - - where not t.getLocation() = "north" - -If the thief has brown hair *or* black hair, you can use: - -.. code-block:: ql - - where t.getHairColor() = "brown" or t.getHairColor() = "black" - -You can also combine these connectives into longer statements: - -.. code-block:: ql - - where t.getAge() > 30 - and (t.getHairColor() = "brown" or t.getHairColor() = "black") - and not t.getLocation() = "north" - -.. pull-quote:: - - Note - - We've placed parentheses around the ``or`` clause to make sure that the query is evaluated as intended. Without parentheses, the connective ``and`` takes precedence over ``or``. - -Predicates don't always return exactly one value. For example, if a person ``p`` has black hair which is turning gray, ``p.getHairColor()`` will return two values: black and gray. - -What if the thief is bald? In that case, the thief has no hair, so the ``getHairColor()`` predicate simply doesn't return any results! - -If you know that the thief definitely isn't bald, then there must be a color that matches the thief's hair color. One way to express this in QL is to introduce a new variable ``c`` of type ``string`` and select those ``t`` where ``t.getHairColor()`` matches a value of ``c``. - -.. code-block:: ql - - from Person t, string c - where t.getHairColor() = c - select t - -Notice that we have only temporarily introduced the variable ``c`` and we didn't need it at all in the ``select`` clause. In this case, it is better to use ``exists``: - -.. code-block:: ql - - from Person t - where exists(string c | t.getHairColor() = c) - select t - -``exists`` introduces a temporary variable ``c`` of type ``string`` and holds only if there is at least one ``string c`` that satisfies ``t.getHairColor() = c``. - -.. pull-quote:: - - Note - - If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier `__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``. - -The real investigation ----------------------- - -You are now ready to track down the thief! Using the examples above, write a query to find the people who satisfy the answers to the first eight questions: - -+---+--------------------------------------------------------+--------+ -| | Question | Answer | -+===+========================================================+========+ -| 1 | Is the thief taller than 150 cm? | yes | -+---+--------------------------------------------------------+--------+ -| 2 | Does the thief have blond hair? | no | -+---+--------------------------------------------------------+--------+ -| 3 | Is the thief bald? | no | -+---+--------------------------------------------------------+--------+ -| 4 | Is the thief younger than 30? | no | -+---+--------------------------------------------------------+--------+ -| 5 | Does the thief live east of the castle? | yes | -+---+--------------------------------------------------------+--------+ -| 6 | Does the thief have black or brown hair? | yes | -+---+--------------------------------------------------------+--------+ -| 7 | Is the thief taller than 180cm and shorter than 190cm? | no | -+---+--------------------------------------------------------+--------+ -| 8 | Is the thief the oldest person in the village? | no | -+---+--------------------------------------------------------+--------+ - -Hints -^^^^^ - -#. Don't forget to ``import tutorial``! -#. Translate each question into QL separately. Look at the examples above if you get stuck. -#. For question 3, remember that a bald person does not have a hair color. -#. For question 8, note that if a person is *not* the oldest, then there is at least one person who is older than them. -#. Combine the conditions using logical connectives to get a query of the form: - -.. code-block:: ql - - import tutorial - - from Person t - where and - not and - ... - select t - -Once you have finished, you will have a list of possible suspects. One of those people must be the thief! - -➤ `See the answer in the query console `__ - -.. pull-quote:: - - Note - - In the answer, we used ``/*`` and ``*/`` to label the different parts of the query. Any text surrounded by ``/*`` and ``*/`` is not evaluated as part of the QL code, but is just a *comment*. - -You are getting closer to solving the mystery! Unfortunately, you still have quite a long list of suspects... To find out which of your suspects is the thief, you must gather more information and refine your query in the :doc:`next step `. diff --git a/docs/language/learn-ql/beginner/find-thief-3.rst b/docs/language/learn-ql/beginner/find-thief-3.rst deleted file mode 100644 index f8323147cf1..00000000000 --- a/docs/language/learn-ql/beginner/find-thief-3.rst +++ /dev/null @@ -1,80 +0,0 @@ -Find the thief: More advanced queries -===================================== - -What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates `__. - -In general, an aggregate is a function that performs an operation on multiple pieces of data and returns a single value as its output. Common aggregates are ``count``, ``max``, ``min``, ``avg`` (average) and ``sum``. The general way to use an aggregate is: - -.. code-block:: ql - - ( | | ) - -For example, you can use the ``max`` aggregate to find the age of the oldest person in the village: - -.. code-block:: ql - - max(int i | exists(Person p | p.getAge() = i) | i) - -This aggregate considers all integers ``i``, limits ``i`` to values that match the ages of people in the village, and then returns the largest matching integer. - -But how can you use this in an actual query? - -If the thief is the oldest person in the village, then you know that the thief's age is equal to the maximum age of the villagers: - -.. code-block:: ql - - from Person t - where t.getAge() = max(int i | exists(Person p | p.getAge() = i) | i) - select t - -This general aggregate syntax is quite long and inconvenient. In most cases, you can omit certain parts of the aggregate. A particularly helpful QL feature is *ordered aggregation*. This allows you to order the expression using ``order by``. - -For example, selecting the oldest villager becomes much simpler if you use an ordered aggregate. - -.. code-block:: ql - - select max(Person p | | p order by p.getAge()) - -The ordered aggregate considers every person ``p`` and selects the person with the maximum age. In this case, there are no restrictions on what people to consider, so the ```` clause is empty. Note that if there are several people with the same maximum age, the query lists all of them. - -Here are some more examples of aggregates: - -+-------------------------------------------------------------------------+---------------------------------------------------+ -| Example | Result | -+=========================================================================+===================================================+ -| ``min(Person p | p.getLocation() = "east" | p order by p.getHeight())`` | shortest person in the east of the village | -+-------------------------------------------------------------------------+---------------------------------------------------+ -| ``count(Person p | p.getLocation() = "south" | p)`` | number of people in the south of the village | -+-------------------------------------------------------------------------+---------------------------------------------------+ -| ``avg(Person p | | p.getHeight())`` | average height of the villagers | -+-------------------------------------------------------------------------+---------------------------------------------------+ -| ``sum(Person p | p.getHairColor() = "brown" | p.getAge())`` | combined age of all the villagers with brown hair | -+-------------------------------------------------------------------------+---------------------------------------------------+ - -Capture the culprit -------------------- - -You can now translate the remaining questions into QL: - -+-----+--------------------------------------------------------------------+--------+ -| | Question | Answer | -+=====+====================================================================+========+ -| ... | ... | ... | -+-----+--------------------------------------------------------------------+--------+ -| 9 | Is the thief the tallest person in the village? | no | -+-----+--------------------------------------------------------------------+--------+ -| 10 | Is the thief shorter than the average villager? | yes | -+-----+--------------------------------------------------------------------+--------+ -| 11 | Is the thief the oldest person in the eastern part of the village? | yes | -+-----+--------------------------------------------------------------------+--------+ - -Have you found the thief? - -➤ `See the answer in the query console `__ - -What next? ----------- - -- Help the villagers track down another criminal in the :doc:`next tutorial `. -- Find out more about the concepts you discovered in this tutorial in the `QL language handbook `__. -- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/heir.rst b/docs/language/learn-ql/beginner/heir.rst index 42589f03125..6ef9231cb0e 100644 --- a/docs/language/learn-ql/beginner/heir.rst +++ b/docs/language/learn-ql/beginner/heir.rst @@ -136,7 +136,7 @@ To decide who should inherit the king's fortune, the villagers carefully read th *"The heir to the throne is the closest living relative of the king. Any person with a criminal record will not be considered. If there are multiple candidates, the oldest person is the heir."* -As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief ` and :doc:`Catch the fire starter ` tutorials). +As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief ` and :doc:`Catch the fire starter ` tutorials). ➤ `See the answer in the query console `__ diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index 2f3d6cc5e5d..f6cf292444c 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -16,7 +16,7 @@ some simple examples. Currently the following detective tutorials are available: -- :doc:`Find the thief `—a three part mystery that introduces logical connectives, quantifiers, and aggregates +- :doc:`Find the thief `—a three part mystery that introduces logical connectives, quantifiers, and aggregates - :doc:`Catch the fire starter `—an intriguing search that introduces predicates and classes - :doc:`Crown the rightful heir `—a detective puzzle that introduces recursion From d0d34d6762ece2c0e73035b7a066d8d536644da5 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 01:36:25 +0000 Subject: [PATCH 072/459] Add intro to first tutorial --- docs/language/learn-ql/beginner/find-the-thief.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/language/learn-ql/beginner/find-the-thief.rst b/docs/language/learn-ql/beginner/find-the-thief.rst index cee0a87943c..92b0973fc9f 100644 --- a/docs/language/learn-ql/beginner/find-the-thief.rst +++ b/docs/language/learn-ql/beginner/find-the-thief.rst @@ -1,6 +1,8 @@ Find the thief ============== +Take on the role of a detective to find the thief in this fictional village. You will learn how to use logical connectives, quantifiers, and aggregates in QL along the way. + Introduction ------------ From 992c61a0a34202cc79cbb372560b5a13909557a1 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 01:41:36 +0000 Subject: [PATCH 073/459] Combine and rename second detective tutorial --- ...{fire-1.rst => catch-the-fire-starter.rst} | 50 +++++++++++++++++-- .../learn-ql/beginner/find-the-thief.rst | 2 +- docs/language/learn-ql/beginner/fire-2.rst | 43 ---------------- docs/language/learn-ql/beginner/heir.rst | 2 +- .../learn-ql/beginner/ql-tutorials.rst | 2 +- 5 files changed, 50 insertions(+), 49 deletions(-) rename docs/language/learn-ql/beginner/{fire-1.rst => catch-the-fire-starter.rst} (75%) delete mode 100644 docs/language/learn-ql/beginner/fire-2.rst diff --git a/docs/language/learn-ql/beginner/fire-1.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst similarity index 75% rename from docs/language/learn-ql/beginner/fire-1.rst rename to docs/language/learn-ql/beginner/catch-the-fire-starter.rst index d5427b56d5f..97d9428d2b5 100644 --- a/docs/language/learn-ql/beginner/fire-1.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -1,5 +1,5 @@ -Catch the fire starter: Classes and predicates -============================================== +Catch the fire starter +====================== Just as you've successfully found the thief and returned the golden crown to the castle, another terrible crime is committed. Early in the morning, a few people start a fire in a field in the north of the village and destroy all the crops! @@ -103,4 +103,48 @@ You know that the fire starters live in the south *and* that they must have been ➤ `See the answer in the query console `__ -Continue to the :doc:`next page ` to gather more clues and find out which of your suspects started the fire... +You can now continue to gather more clues and find out which of your suspects started the fire... + +Identify the bald bandits +------------------------- + +You ask the northerners if they have any more information about the fire starters. Luckily, you have a witness! The farmer living next to the field saw two people run away just after the fire started. He only saw the tops of their heads, and noticed that they were both bald. + +This is a very helpful clue. Remember that you wrote a QL query to select all bald people: + +.. code-block:: ql + + from Person p + where not exists (string c | p.getHairColor() = c) + select p + +To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``isBald``. + +.. code-block:: ql + + predicate isBald(Person p) { + not exists (string c | p.getHairColor() = c) + } + +The property ``isBald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with: + +.. code-block:: ql + + from Person p + where isBald(p) + select p + +The predicate ``isBald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for example—that would cause an error. + +You can now write a query to select the bald southerners who are allowed into the north. + +➤ `See the answer in the query console `__ + +You have found the two fire starters! They are arrested and the villagers are once again impressed with your work. + +What next? +---------- + +- Find out who will be the new ruler of the village in the :doc:`next tutorial `. +- Learn more about predicates and classes in the `QL language handbook `__. +- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/find-the-thief.rst b/docs/language/learn-ql/beginner/find-the-thief.rst index 92b0973fc9f..3172f98e511 100644 --- a/docs/language/learn-ql/beginner/find-the-thief.rst +++ b/docs/language/learn-ql/beginner/find-the-thief.rst @@ -292,6 +292,6 @@ Have you found the thief? What next? ---------- -- Help the villagers track down another criminal in the :doc:`next tutorial `. +- Help the villagers track down another criminal in the :doc:`next tutorial `. - Find out more about the concepts you discovered in this tutorial in the `QL language handbook `__. - Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/fire-2.rst b/docs/language/learn-ql/beginner/fire-2.rst deleted file mode 100644 index 0f5312e69f0..00000000000 --- a/docs/language/learn-ql/beginner/fire-2.rst +++ /dev/null @@ -1,43 +0,0 @@ -Catch the fire starter: Bald bandits -==================================== - -You ask the northerners if they have any more information about the fire starters. Luckily, you have a witness! The farmer living next to the field saw two people run away just after the fire started. He only saw the tops of their heads, and noticed that they were both bald. - -This is a very helpful clue. Remember that you wrote a QL query to select all bald people: - -.. code-block:: ql - - from Person p - where not exists (string c | p.getHairColor() = c) - select p - -To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``isBald``. - -.. code-block:: ql - - predicate isBald(Person p) { - not exists (string c | p.getHairColor() = c) - } - -The property ``isBald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with: - -.. code-block:: ql - - from Person p - where isBald(p) - select p - -The predicate ``isBald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for example—that would cause an error. - -You can now write a query to select the bald southerners who are allowed into the north. - -➤ `See the answer in the query console `__ - -You have found the two fire starters! They are arrested and the villagers are once again impressed with your work. - -What next? ----------- - -- Find out who will be the new ruler of the village in the :doc:`next tutorial `. -- Learn more about predicates and classes in the `QL language handbook `__. -- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/heir.rst b/docs/language/learn-ql/beginner/heir.rst index 6ef9231cb0e..82b25e31dbe 100644 --- a/docs/language/learn-ql/beginner/heir.rst +++ b/docs/language/learn-ql/beginner/heir.rst @@ -136,7 +136,7 @@ To decide who should inherit the king's fortune, the villagers carefully read th *"The heir to the throne is the closest living relative of the king. Any person with a criminal record will not be considered. If there are multiple candidates, the oldest person is the heir."* -As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief ` and :doc:`Catch the fire starter ` tutorials). +As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief ` and :doc:`Catch the fire starter ` tutorials). ➤ `See the answer in the query console `__ diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index f6cf292444c..4a8ee58c5fb 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -17,7 +17,7 @@ some simple examples. Currently the following detective tutorials are available: - :doc:`Find the thief `—a three part mystery that introduces logical connectives, quantifiers, and aggregates -- :doc:`Catch the fire starter `—an intriguing search that introduces predicates and classes +- :doc:`Catch the fire starter `—an intriguing search that introduces predicates and classes - :doc:`Crown the rightful heir `—a detective puzzle that introduces recursion Further resources From 570e726ab57422893905b3d45b32c3433c1620c8 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 01:45:23 +0000 Subject: [PATCH 074/459] Add intro to second tutorial --- docs/language/learn-ql/beginner/catch-the-fire-starter.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst index 97d9428d2b5..19443f77aa8 100644 --- a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -1,6 +1,8 @@ Catch the fire starter ====================== +You can use QL predicates and classes to solve your second mystery as a QL detective. + Just as you've successfully found the thief and returned the golden crown to the castle, another terrible crime is committed. Early in the morning, a few people start a fire in a field in the north of the village and destroy all the crops! You now have the reputation of being an expert QL detective, so you are once again asked to find the culprits. From fdfa2e1aebd18e6a8a2929d29a558e1a3dca3df0 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 01:49:28 +0000 Subject: [PATCH 075/459] Rename third detective tutorial --- docs/language/learn-ql/beginner/catch-the-fire-starter.rst | 2 +- .../learn-ql/beginner/{heir.rst => crown-the-rightful-heir.rst} | 0 docs/language/learn-ql/beginner/ql-tutorials.rst | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename docs/language/learn-ql/beginner/{heir.rst => crown-the-rightful-heir.rst} (100%) diff --git a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst index 19443f77aa8..75e6370997d 100644 --- a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -147,6 +147,6 @@ You have found the two fire starters! They are arrested and the villagers are on What next? ---------- -- Find out who will be the new ruler of the village in the :doc:`next tutorial `. +- Find out who will be the new ruler of the village in the :doc:`next tutorial `. - Learn more about predicates and classes in the `QL language handbook `__. - Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst similarity index 100% rename from docs/language/learn-ql/beginner/heir.rst rename to docs/language/learn-ql/beginner/crown-the-rightful-heir.rst diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index 4a8ee58c5fb..d52875c1955 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -18,7 +18,7 @@ Currently the following detective tutorials are available: - :doc:`Find the thief `—a three part mystery that introduces logical connectives, quantifiers, and aggregates - :doc:`Catch the fire starter `—an intriguing search that introduces predicates and classes -- :doc:`Crown the rightful heir `—a detective puzzle that introduces recursion +- :doc:`Crown the rightful heir `—a detective puzzle that introduces recursion Further resources ----------------- From fe71cc79baff1d4d46381edec3405f24b6d7b40d Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 01:53:47 +0000 Subject: [PATCH 076/459] Add intro to third tutorial --- .../learn-ql/beginner/crown-the-rightful-heir.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst index 82b25e31dbe..0f0168f80a3 100644 --- a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst +++ b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst @@ -1,6 +1,11 @@ Crown the rightful heir ======================= +This is QL detective puzzle that shows you how to use recursion in QL to write more complex queries. + +King Basil's heir +----------------- + Phew! No more crimes in the village—you can finally leave the village and go home. But then... During your last night in the village, the old king—the great King Basil—dies in his sleep and there is chaos everywhere! @@ -9,9 +14,6 @@ The king never married and he had no children, so nobody knows who should inheri Eventually you decide to stay in the village to resolve the argument and find the true heir to the throne. -King Basil's heir ------------------ - You want to find out if anyone in the village is actually related to the king. This seems like a difficult task at first, but you start work confidently. You know the villagers quite well by now, and you have a list of all the parents in the village and their children. To find out more about the king and his family, you get access to the castle and find some old family trees. You also include these relations in your database to see if anyone in the king's family is still alive. From 8c5580fe5b897bf022e24eab86cd56f7039a9f0d Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 02:13:51 +0000 Subject: [PATCH 077/459] Reorganize map topic --- .../learn-ql/beginner/ql-tutorials.rst | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index d52875c1955..4d706c91199 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -1,27 +1,14 @@ -QL detective tutorials -====================== +QL tutorials +============ + +Solve puzzles to learn the basics of QL before analyzing code with CodeQL. The tutorials teach you how to write queries and introduce you to key logic concepts along the way. + +Before starting these tutorials, you can read the :doc:`Introduction to QL <../introduction-to-ql>` for a description of the language and some simple examples. .. toctree:: :glob: :hidden: - ./* - -Welcome to the detective tutorials! These are aimed at complete beginners who would like to learn the basics of QL, -before analyzing code with CodeQL. -The tutorials teach you how to write queries and introduce you to key logic concepts along the way. - -We recommend you first read the :doc:`Introduction to QL <../introduction-to-ql>` page for a description of the language and -some simple examples. - -Currently the following detective tutorials are available: - -- :doc:`Find the thief `—a three part mystery that introduces logical connectives, quantifiers, and aggregates -- :doc:`Catch the fire starter `—an intriguing search that introduces predicates and classes -- :doc:`Crown the rightful heir `—a detective puzzle that introduces recursion - -Further resources ------------------ - -- For a summary of available learning resources, see :doc:`Learning CodeQL <../../index>`. -- For an overview of the important concepts in QL, see the `QL language handbook `__. + find-the-thief + catch-the-fire-starter + crown-the-rightful-heir \ No newline at end of file From 30e41dd4da6805a655b777b3bf5c2908166c4a66 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 02:14:39 +0000 Subject: [PATCH 078/459] Update references to QL tutorials --- docs/language/learn-ql/introduction-to-ql.rst | 2 +- docs/language/ql-handbook/name-resolution.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index 4945d713803..e6ff509f570 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -163,6 +163,6 @@ Java Learning CodeQL --------------- -- To find out more about how to write your own queries, try working through the :doc:`QL detective tutorials `. +- To find out more about how to write your own queries, try working through the :doc:`QL tutorials `. - For an overview of the other available resources, see :doc:`Learning CodeQL <../index>`. - For a more technical description of the underlying language, see :doc:`About QL `. diff --git a/docs/language/ql-handbook/name-resolution.rst b/docs/language/ql-handbook/name-resolution.rst index 6c6bd47e6fe..430e80173f0 100644 --- a/docs/language/ql-handbook/name-resolution.rst +++ b/docs/language/ql-handbook/name-resolution.rst @@ -240,7 +240,7 @@ and the global namespaces. (You can think of global namespaces as the enclosing Let's see what the module, type, and predicate namespaces look like in a concrete example: For example, you could define a library module ``Villagers`` containing some of the classes and predicates that -were defined in the `QL detective tutorials `_: +were defined in the `QL tutorials `_: **Villagers.qll** From 52ffd91a2699b558958171a07ab4de63bbd85d13 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 02:25:56 +0000 Subject: [PATCH 079/459] Move "River crossing puzzle" into tutorial folder - Update links - Delete "QL etudes" folder --- .../river-crossing.rst => beginner/cross-the-river.rst} | 0 docs/language/learn-ql/beginner/crown-the-rightful-heir.rst | 2 +- docs/language/learn-ql/beginner/ql-tutorials.rst | 4 ++-- .../learn-ql/{ql-etudes => beginner}/river-crossing-1.ql | 0 .../learn-ql/{ql-etudes => beginner}/river-crossing.ql | 0 docs/language/learn-ql/index.rst | 1 - 6 files changed, 3 insertions(+), 4 deletions(-) rename docs/language/learn-ql/{ql-etudes/river-crossing.rst => beginner/cross-the-river.rst} (100%) rename docs/language/learn-ql/{ql-etudes => beginner}/river-crossing-1.ql (100%) rename docs/language/learn-ql/{ql-etudes => beginner}/river-crossing.ql (100%) diff --git a/docs/language/learn-ql/ql-etudes/river-crossing.rst b/docs/language/learn-ql/beginner/cross-the-river.rst similarity index 100% rename from docs/language/learn-ql/ql-etudes/river-crossing.rst rename to docs/language/learn-ql/beginner/cross-the-river.rst diff --git a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst index 0f0168f80a3..6f740e2bf79 100644 --- a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst +++ b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst @@ -162,5 +162,5 @@ What next? ---------- - Learn more about recursion in the `QL language handbook `__. -- Put your QL skills to the test and solve the :doc:`River crossing puzzle <../ql-etudes/river-crossing>`. +- Put your QL skills to the test and solve the :doc:`River crossing puzzle `. - Start using QL to analyze projects. See :doc:`Learning CodeQL <../../index>` for a summary of the available languages and resources. diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index 4d706c91199..5b7dab7177b 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -7,8 +7,8 @@ Before starting these tutorials, you can read the :doc:`Introduction to QL <../i .. toctree:: :glob: - :hidden: find-the-thief catch-the-fire-starter - crown-the-rightful-heir \ No newline at end of file + crown-the-rightful-heir + cross-the-river \ No newline at end of file diff --git a/docs/language/learn-ql/ql-etudes/river-crossing-1.ql b/docs/language/learn-ql/beginner/river-crossing-1.ql similarity index 100% rename from docs/language/learn-ql/ql-etudes/river-crossing-1.ql rename to docs/language/learn-ql/beginner/river-crossing-1.ql diff --git a/docs/language/learn-ql/ql-etudes/river-crossing.ql b/docs/language/learn-ql/beginner/river-crossing.ql similarity index 100% rename from docs/language/learn-ql/ql-etudes/river-crossing.ql rename to docs/language/learn-ql/beginner/river-crossing.ql diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index f25bf8bb644..4849f7816c7 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -34,7 +34,6 @@ If you are new to QL, start by looking at the following topics: introduction-to-ql about-ql beginner/ql-tutorials - ql-etudes/river-crossing CodeQL training and variant analysis examples ********************************************* From 327486dc580c31c132783841ae49a411575b1bcc Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 02:35:21 +0000 Subject: [PATCH 080/459] Update title and intro for river crossing puzzle --- docs/language/learn-ql/beginner/cross-the-river.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/beginner/cross-the-river.rst b/docs/language/learn-ql/beginner/cross-the-river.rst index fef3363a08b..3c48ce09667 100644 --- a/docs/language/learn-ql/beginner/cross-the-river.rst +++ b/docs/language/learn-ql/beginner/cross-the-river.rst @@ -1,7 +1,10 @@ -River crossing puzzle -##################### +Cross the river +=============== -The aim of this tutorial is to write a query that finds a solution to the following classical logic puzzle: +You can use common QL features to write a query that finds a solution to the "River crossing" logic puzzle. + +Introduction +------------ .. pull-quote:: From a9d76cbe647f10177e30e31a618c77a212ebf09c Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 11 Mar 2020 10:28:31 +0100 Subject: [PATCH 081/459] Dataflow: Add consistency checks for toString and location. --- .../internal/DataFlowImplConsistency.qll | 38 +++++++++++++++++++ .../internal/DataFlowImplConsistency.qll | 38 +++++++++++++++++++ .../internal/DataFlowImplConsistency.qll | 38 +++++++++++++++++++ .../internal/DataFlowImplConsistency.qll | 38 +++++++++++++++++++ 4 files changed, 152 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll index 60130a1aea9..0dc3b8eff45 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -55,6 +55,44 @@ module Consistency { ) } + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + query predicate parameterCallable(ParameterNode p, string msg) { exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and msg = "Callable mismatch for parameter." diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll index 60130a1aea9..0dc3b8eff45 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -55,6 +55,44 @@ module Consistency { ) } + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + query predicate parameterCallable(ParameterNode p, string msg) { exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and msg = "Callable mismatch for parameter." diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll index 60130a1aea9..0dc3b8eff45 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -55,6 +55,44 @@ module Consistency { ) } + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + query predicate parameterCallable(ParameterNode p, string msg) { exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and msg = "Callable mismatch for parameter." diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index 60130a1aea9..0dc3b8eff45 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -55,6 +55,44 @@ module Consistency { ) } + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + query predicate parameterCallable(ParameterNode p, string msg) { exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and msg = "Callable mismatch for parameter." From 85d6b7c2ed308f284baceb109de852c7dac5dc28 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 11 Mar 2020 10:49:21 +0100 Subject: [PATCH 082/459] C++: Add tests. --- .../dataflow-consistency.expected | 261 ++++ .../dataflow-tests/dataflow-consistency.ql | 1 + .../dataflow-ir-consistency.expected | 354 ++++++ .../dataflow-tests/dataflow-ir-consistency.ql | 1 + .../fields/dataflow-consistency.expected | 134 ++ .../dataflow/fields/dataflow-consistency.ql | 1 + .../fields/dataflow-ir-consistency.expected | 338 +++++ .../fields/dataflow-ir-consistency.ql | 1 + .../syntax-zoo/dataflow-consistency.expected | 286 +++++ .../syntax-zoo/dataflow-consistency.ql | 1 + .../dataflow-ir-consistency.expected | 1105 +++++++++++++++++ .../syntax-zoo/dataflow-ir-consistency.ql | 1 + 12 files changed, 2484 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected create mode 100644 cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.ql create mode 100644 cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected create mode 100644 cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.ql create mode 100644 cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected create mode 100644 cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.ql create mode 100644 cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected create mode 100644 cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.ql create mode 100644 cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected create mode 100644 cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.ql create mode 100644 cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected create mode 100644 cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.ql diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected new file mode 100644 index 00000000000..f024791bf06 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -0,0 +1,261 @@ +uniqueEnclosingCallable +uniqueTypeBound +uniqueTypeRepr +uniqueNodeLocation +| dispatch.cpp:60:18:60:29 | call to Bottom | Node should have one location but has 2. | +| dispatch.cpp:61:18:61:29 | call to Middle | Node should have one location but has 2. | +| dispatch.cpp:65:10:65:21 | call to Bottom | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Bottom | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Bottom | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Middle | Node should have one location but has 2. | +missingLocation +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| BarrierGuard.cpp:6:15:6:20 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:7:10:7:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:9:10:9:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:14:16:14:21 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:15:10:15:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:17:10:17:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:22:15:22:20 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:23:10:23:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:25:10:25:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:30:15:30:20 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:31:10:31:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:33:10:33:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:38:16:38:21 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:41:8:41:13 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:50:18:50:18 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:51:13:51:13 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:52:25:52:25 | y | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:53:13:53:13 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:54:25:54:25 | y | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:55:13:55:13 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:61:19:61:19 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:62:14:62:14 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:63:26:63:26 | y | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:64:14:64:14 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:65:26:65:26 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:66:14:66:14 | x | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:12:8:12:8 | x | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:19:27:19:32 | call to source | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:28:8:28:8 | x | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:34:8:34:8 | x | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:41:19:41:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:18:8:18:19 | sourceArray1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:20:8:20:22 | access to array | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:21:8:21:20 | * ... | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:24:22:24:23 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:25:27:25:28 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:26:27:26:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:29:27:29:28 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:30:27:30:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:31:27:31:28 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:32:22:32:23 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:37:10:37:11 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:41:18:41:19 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:45:17:45:18 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:47:8:47:30 | call to expression | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:51:8:51:17 | stackArray | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:11:38:11:38 | x | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:23:38:23:38 | x | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:31:16:31:24 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:32:16:32:24 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:33:18:33:23 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:35:16:35:25 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:36:16:36:25 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:37:19:37:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:39:15:39:23 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:40:15:40:23 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:41:17:41:22 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:43:15:43:24 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:44:15:44:24 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:45:18:45:23 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:55:22:55:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:56:22:56:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:58:28:58:36 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:69:15:69:20 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:73:14:73:19 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:77:21:77:34 | call to allocateBottom | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:78:23:78:39 | * ... | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:81:13:81:18 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:89:28:89:33 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:90:25:90:30 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:96:8:96:8 | x | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:107:17:107:22 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:108:16:108:21 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:129:18:129:25 | call to isSource | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:130:17:130:24 | call to isSource | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:140:8:140:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:144:8:144:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:153:37:153:37 | f | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:154:37:154:37 | g | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:160:8:160:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:164:8:164:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:173:42:173:42 | f | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:174:42:174:42 | g | ArgumentNode is missing PostUpdateNode. | +| globals.cpp:6:10:6:14 | local | ArgumentNode is missing PostUpdateNode. | +| globals.cpp:12:10:12:24 | flowTestGlobal1 | ArgumentNode is missing PostUpdateNode. | +| globals.cpp:19:10:19:24 | flowTestGlobal2 | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:14:3:14:6 | t | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:15:3:15:6 | u | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:18:7:18:7 | a | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:18:8:18:8 | call to operator() | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:21:3:21:6 | t | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:22:3:22:6 | u | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:25:2:25:2 | b | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:26:7:26:7 | v | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:29:3:29:6 | t | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:30:3:30:6 | u | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:32:2:32:2 | c | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:35:8:35:8 | a | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:36:8:36:8 | b | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:38:2:38:2 | d | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:38:4:38:4 | t | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:38:7:38:7 | u | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:41:8:41:8 | a | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:42:8:42:8 | b | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:45:2:45:2 | e | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:46:7:46:7 | w | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:16:12:16:14 | lhs | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:16:17:16:19 | rhs | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:16:17:16:19 | rhs | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:55:23:55:28 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:56:10:56:11 | x1 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:58:19:58:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:59:10:59:11 | x2 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:62:10:62:11 | x3 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:65:10:65:11 | x4 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:79:17:79:19 | rhs | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:122:23:122:28 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:123:13:123:15 | val | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:125:19:125:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:126:13:126:15 | val | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:129:13:129:15 | val | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:132:13:132:15 | val | ArgumentNode is missing PostUpdateNode. | +| test.cpp:7:8:7:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:9:8:9:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:10:8:10:9 | t2 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:13:10:13:11 | t2 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:15:8:15:9 | t2 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:21:8:21:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:26:8:26:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:30:8:30:8 | t | ArgumentNode is missing PostUpdateNode. | +| test.cpp:31:8:31:8 | c | ArgumentNode is missing PostUpdateNode. | +| test.cpp:35:10:35:15 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:35:20:35:20 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:36:10:36:10 | 1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:36:13:36:18 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:43:10:43:20 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:46:10:46:10 | t | ArgumentNode is missing PostUpdateNode. | +| test.cpp:58:10:58:10 | t | ArgumentNode is missing PostUpdateNode. | +| test.cpp:71:8:71:9 | x4 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:76:8:76:9 | u1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:78:8:78:9 | u1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:81:8:81:9 | i1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:84:8:84:18 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:86:8:86:9 | i1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:90:8:90:14 | source1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:92:8:92:14 | source1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:103:10:103:12 | ref | ArgumentNode is missing PostUpdateNode. | +| test.cpp:110:10:110:12 | ref | ArgumentNode is missing PostUpdateNode. | +| test.cpp:138:27:138:32 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:140:8:140:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:144:8:144:8 | s | ArgumentNode is missing PostUpdateNode. | +| test.cpp:149:33:149:33 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:150:8:150:8 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:151:33:151:38 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:152:8:152:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:157:8:157:8 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:162:34:162:34 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:163:8:163:8 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:164:34:164:39 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:165:8:165:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:178:8:178:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:194:29:194:34 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:197:10:197:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:202:10:202:16 | barrier | ArgumentNode is missing PostUpdateNode. | +| test.cpp:207:35:207:35 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:208:10:208:10 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:209:35:209:40 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:210:10:210:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:216:10:216:10 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:221:36:221:36 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:222:10:222:10 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:223:36:223:41 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:224:10:224:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:238:10:238:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:245:14:245:19 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:246:18:246:23 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:251:14:251:14 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:256:14:256:20 | barrier | ArgumentNode is missing PostUpdateNode. | +| test.cpp:260:12:260:12 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:265:22:265:27 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:266:12:266:12 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:267:22:267:27 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:268:12:268:12 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:273:21:273:21 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:278:21:278:27 | barrier | ArgumentNode is missing PostUpdateNode. | +| test.cpp:289:14:289:14 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:291:14:291:14 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:314:4:314:9 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:317:12:317:12 | p | ArgumentNode is missing PostUpdateNode. | +| test.cpp:318:7:318:7 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:319:12:319:12 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:320:7:320:7 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:337:10:337:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:339:10:339:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:343:10:343:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:349:10:349:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:363:10:363:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:365:10:365:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:369:10:369:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:375:10:375:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:384:16:384:23 | & ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:384:26:384:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:385:8:385:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:391:16:391:23 | & ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:391:26:391:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:392:8:392:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:394:10:394:12 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:400:16:400:22 | & ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:400:25:400:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:401:8:401:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:407:16:407:22 | & ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:407:25:407:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:408:8:408:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:418:8:418:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:424:8:424:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:430:8:430:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:431:8:431:13 | * ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:436:26:436:26 | 1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:437:8:437:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:442:25:442:25 | 2 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:443:8:443:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:444:8:444:13 | * ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:450:9:450:22 | (statement expression) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:451:9:451:21 | (statement expression) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:461:8:461:12 | local | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:13:8:13:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:21:8:21:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:29:8:29:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:39:8:39:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:49:8:49:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:57:8:57:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:66:8:66:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:78:8:78:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:86:8:86:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:93:8:93:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:105:8:105:8 | x | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.ql new file mode 100644 index 00000000000..4304a961abe --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected new file mode 100644 index 00000000000..6b847acb3e8 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -0,0 +1,354 @@ +uniqueEnclosingCallable +uniqueTypeBound +uniqueTypeRepr +uniqueNodeLocation +| BarrierGuard.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| acrossLinkTargets.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| clang.cpp:4:11:4:13 | p#0 | Node should have one location but has 6. | +| clang.cpp:4:27:4:35 | p#0 | Node should have one location but has 2. | +| clang.cpp:4:51:4:53 | p#0 | Node should have one location but has 2. | +| dispatch.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| globals.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| test.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| test.cpp:2:27:2:35 | p#0 | Node should have one location but has 2. | +| test.cpp:2:51:2:53 | p#0 | Node should have one location but has 2. | +missingLocation +| Nodes without location: 4 | +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| BarrierGuard.cpp:6:15:6:20 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:7:10:7:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:9:10:9:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:14:16:14:21 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:15:10:15:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:17:10:17:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:22:15:22:20 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:23:10:23:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:25:10:25:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:30:15:30:20 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:31:10:31:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:33:10:33:15 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:38:16:38:21 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:41:8:41:13 | source | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:50:18:50:18 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:51:13:51:13 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:52:25:52:25 | y | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:53:13:53:13 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:54:25:54:25 | y | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:55:13:55:13 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:61:19:61:19 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:62:14:62:14 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:63:26:63:26 | y | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:64:14:64:14 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:65:26:65:26 | x | ArgumentNode is missing PostUpdateNode. | +| BarrierGuard.cpp:66:14:66:14 | x | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:12:8:12:8 | (int)... | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:19:27:19:32 | call to source | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:28:8:28:8 | (int)... | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:34:8:34:8 | (int)... | ArgumentNode is missing PostUpdateNode. | +| acrossLinkTargets.cpp:41:19:41:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:18:8:18:19 | (const int *)... | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:20:8:20:22 | access to array | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:21:8:21:20 | * ... | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:22:8:22:20 | & ... | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:24:22:24:23 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:25:27:25:28 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:26:8:26:24 | sourceStruct1_ptr | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:26:27:26:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:29:27:29:28 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:30:8:30:24 | sourceStruct1_ptr | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:30:27:30:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:31:27:31:28 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:32:22:32:23 | m1 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:37:10:37:11 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:41:18:41:19 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:45:17:45:18 | m2 | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:47:8:47:30 | call to expression | ArgumentNode is missing PostUpdateNode. | +| clang.cpp:51:8:51:17 | (const int *)... | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:11:38:11:38 | x | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:15:8:15:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:21:8:21:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:23:38:23:38 | x | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:31:8:31:13 | topPtr | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:31:16:31:24 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:32:8:32:13 | topPtr | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:32:16:32:24 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:33:3:33:8 | topPtr | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:33:18:33:23 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:35:8:35:13 | topPtr | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:35:16:35:25 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:36:8:36:13 | topPtr | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:36:16:36:25 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:37:3:37:8 | topPtr | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:37:19:37:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:39:8:39:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:39:15:39:23 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:40:8:40:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:40:15:40:23 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:41:3:41:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:41:17:41:22 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:43:8:43:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:43:15:43:24 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:44:8:44:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:44:15:44:24 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:45:3:45:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:45:18:45:23 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:55:8:55:19 | globalBottom | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:55:22:55:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:56:8:56:19 | globalMiddle | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:56:22:56:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:58:8:58:23 | call to readGlobalBottom | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:58:28:58:36 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:60:18:60:29 | Constant | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:60:18:60:29 | new | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:61:18:61:29 | Constant | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:61:18:61:29 | new | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:65:10:65:21 | Constant | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:65:10:65:21 | new | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:69:3:69:5 | top | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:69:15:69:20 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:73:3:73:5 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:73:14:73:19 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:77:21:77:34 | call to allocateBottom | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:78:23:78:39 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:81:3:81:3 | x | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:81:13:81:18 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:89:3:89:10 | call to identity | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:89:12:89:17 | (Top *)... | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:89:28:89:33 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:90:3:90:10 | call to identity | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:90:12:90:14 | top | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:90:25:90:30 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:96:8:96:8 | x | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:107:17:107:22 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:108:16:108:21 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:129:10:129:15 | topPtr | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:129:18:129:25 | call to isSource | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:130:10:130:15 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:130:17:130:24 | call to isSource | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:140:8:140:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:144:8:144:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:153:37:153:37 | f | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:154:37:154:37 | g | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:160:8:160:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:164:8:164:13 | call to source | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:173:42:173:42 | f | ArgumentNode is missing PostUpdateNode. | +| dispatch.cpp:174:42:174:42 | g | ArgumentNode is missing PostUpdateNode. | +| example.c:26:18:26:24 | & ... | ArgumentNode is missing PostUpdateNode. | +| example.c:28:14:28:25 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | t | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | t | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | u | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | u | ArgumentNode is missing PostUpdateNode. | +| globals.cpp:6:10:6:14 | local | ArgumentNode is missing PostUpdateNode. | +| globals.cpp:12:10:12:24 | flowTestGlobal1 | ArgumentNode is missing PostUpdateNode. | +| globals.cpp:19:10:19:24 | flowTestGlobal2 | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:18:7:18:7 | (const lambda [] type at line 13, col. 11)... | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:18:8:18:8 | call to operator() | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:21:8:21:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:22:8:22:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:25:2:25:2 | (const lambda [] type at line 20, col. 11)... | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:26:7:26:7 | v | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:32:2:32:2 | (const lambda [] type at line 28, col. 11)... | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:35:8:35:8 | a | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:36:8:36:8 | b | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:38:2:38:2 | (const lambda [] type at line 34, col. 11)... | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:38:4:38:4 | t | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:38:7:38:7 | u | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:41:8:41:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:42:8:42:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:45:2:45:2 | (const lambda [] type at line 40, col. 11)... | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:45:4:45:4 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:45:7:45:7 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:45:10:45:10 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:46:7:46:7 | w | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:16:12:16:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:16:17:16:19 | rhs | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:37:21:37:23 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:55:19:55:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:55:23:55:28 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:56:10:56:11 | x1 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:58:15:58:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:58:19:58:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:59:10:59:11 | x2 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:61:26:61:27 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:62:10:62:11 | x3 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:64:15:64:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:65:10:65:11 | x4 | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:79:12:79:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:79:17:79:19 | rhs | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:102:21:102:23 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:122:19:122:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:122:23:122:28 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:123:13:123:15 | val | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:125:15:125:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:125:19:125:24 | call to source | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:126:13:126:15 | val | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:128:26:128:27 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:129:13:129:15 | val | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:131:15:131:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ref.cpp:132:13:132:15 | val | ArgumentNode is missing PostUpdateNode. | +| test.cpp:7:8:7:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:9:8:9:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:10:8:10:9 | t2 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:13:10:13:11 | t2 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:15:8:15:9 | t2 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:21:8:21:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:26:8:26:9 | t1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:30:8:30:8 | t | ArgumentNode is missing PostUpdateNode. | +| test.cpp:31:8:31:8 | c | ArgumentNode is missing PostUpdateNode. | +| test.cpp:35:10:35:15 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:35:20:35:20 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:36:10:36:10 | 1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:36:13:36:18 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:43:10:43:20 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:46:10:46:10 | t | ArgumentNode is missing PostUpdateNode. | +| test.cpp:58:10:58:10 | t | ArgumentNode is missing PostUpdateNode. | +| test.cpp:67:29:67:35 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:71:8:71:9 | x4 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:76:8:76:9 | u1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:78:8:78:9 | u1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:81:8:81:9 | i1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:84:8:84:18 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:86:8:86:9 | i1 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:90:8:90:14 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:92:8:92:14 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:103:10:103:12 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:110:10:110:12 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:138:27:138:32 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:140:8:140:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:144:8:144:8 | s | ArgumentNode is missing PostUpdateNode. | +| test.cpp:149:33:149:33 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:150:8:150:8 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:151:33:151:38 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:152:8:152:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:157:8:157:8 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:162:34:162:34 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:163:8:163:8 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:164:34:164:39 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:165:8:165:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:178:8:178:8 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:194:29:194:34 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:197:10:197:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:202:10:202:16 | barrier | ArgumentNode is missing PostUpdateNode. | +| test.cpp:207:35:207:35 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:208:10:208:10 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:209:35:209:40 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:210:10:210:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:216:10:216:10 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:221:36:221:36 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:222:10:222:10 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:223:36:223:41 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:224:10:224:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:238:10:238:10 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:245:14:245:19 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:246:18:246:23 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:251:14:251:14 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:256:14:256:20 | barrier | ArgumentNode is missing PostUpdateNode. | +| test.cpp:260:12:260:12 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:265:22:265:27 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:266:12:266:12 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:267:22:267:27 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:268:12:268:12 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:273:21:273:21 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:278:21:278:27 | barrier | ArgumentNode is missing PostUpdateNode. | +| test.cpp:289:14:289:14 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:291:14:291:14 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:314:4:314:9 | call to source | ArgumentNode is missing PostUpdateNode. | +| test.cpp:317:12:317:12 | p | ArgumentNode is missing PostUpdateNode. | +| test.cpp:318:7:318:7 | x | ArgumentNode is missing PostUpdateNode. | +| test.cpp:319:12:319:12 | 0 | ArgumentNode is missing PostUpdateNode. | +| test.cpp:320:7:320:7 | y | ArgumentNode is missing PostUpdateNode. | +| test.cpp:337:10:337:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:339:10:339:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:343:10:343:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:349:10:349:18 | globalVar | ArgumentNode is missing PostUpdateNode. | +| test.cpp:363:10:363:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:365:10:365:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:369:10:369:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:375:10:375:14 | field | ArgumentNode is missing PostUpdateNode. | +| test.cpp:384:10:384:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:384:16:384:23 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:384:26:384:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:385:8:385:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:391:10:391:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:391:16:391:23 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:391:26:391:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:392:8:392:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:394:10:394:12 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:400:10:400:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:400:16:400:22 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:400:25:400:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:401:8:401:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:407:10:407:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:407:16:407:22 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:407:25:407:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | +| test.cpp:408:8:408:10 | tmp | ArgumentNode is missing PostUpdateNode. | +| test.cpp:417:16:417:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:418:8:418:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:423:20:423:25 | & ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:424:8:424:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:429:20:429:24 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| test.cpp:430:8:430:12 | (const int *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:431:8:431:13 | * ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:436:18:436:23 | & ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:436:26:436:26 | (size_t)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:437:8:437:12 | local | ArgumentNode is missing PostUpdateNode. | +| test.cpp:442:18:442:22 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| test.cpp:442:25:442:25 | (size_t)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:443:8:443:12 | (const int *)... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:444:8:444:13 | * ... | ArgumentNode is missing PostUpdateNode. | +| test.cpp:450:9:450:22 | (statement expression) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:451:9:451:21 | (statement expression) | ArgumentNode is missing PostUpdateNode. | +| test.cpp:461:8:461:12 | local | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:13:8:13:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:21:8:21:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:29:8:29:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:39:8:39:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:49:8:49:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:57:8:57:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:66:8:66:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:78:8:78:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:86:8:86:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:93:8:93:8 | x | ArgumentNode is missing PostUpdateNode. | +| true_upon_entry.cpp:105:8:105:8 | x | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.ql new file mode 100644 index 00000000000..6d9f8e314f7 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected new file mode 100644 index 00000000000..137400639a8 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -0,0 +1,134 @@ +uniqueEnclosingCallable +| C.cpp:37:24:37:33 | 0 | Node should have one enclosing callable but has 0. | +| C.cpp:37:24:37:33 | new | Node should have one enclosing callable but has 0. | +uniqueTypeBound +| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type bound but has 0. | +| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type bound but has 0. | +uniqueTypeRepr +| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type representation but has 0. | +| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type representation but has 0. | +uniqueNodeLocation +| A.cpp:38:7:38:8 | call to C | Node should have one location but has 2. | +| A.cpp:39:7:39:8 | call to C | Node should have one location but has 2. | +| A.cpp:41:15:41:21 | call to C | Node should have one location but has 2. | +| A.cpp:47:12:47:18 | call to C | Node should have one location but has 2. | +| A.cpp:57:17:57:23 | call to C | Node should have one location but has 2. | +| A.cpp:64:21:64:28 | call to C2 | Node should have one location but has 2. | +| A.cpp:73:25:73:32 | call to C2 | Node should have one location but has 2. | +| A.cpp:126:12:126:18 | call to C | Node should have one location but has 2. | +| A.cpp:142:14:142:20 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C2 | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C2 | Node should have one location but has 2. | +missingLocation +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| A.cpp:40:15:40:21 | 0 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:41:15:41:21 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:55:12:55:19 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:56:13:56:15 | call to get | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:17:57:23 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:28:57:30 | call to get | ArgumentNode is missing PostUpdateNode. | +| A.cpp:64:21:64:28 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:73:25:73:32 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:126:12:126:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:151:21:151:21 | call to r | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:32:160:59 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:43:160:49 | 0 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:52:160:58 | 0 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:161:29:161:35 | 0 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:162:29:162:35 | 0 | ArgumentNode is missing PostUpdateNode. | +| B.cpp:7:28:7:34 | 0 | ArgumentNode is missing PostUpdateNode. | +| B.cpp:16:28:16:34 | 0 | ArgumentNode is missing PostUpdateNode. | +| C.cpp:29:10:29:11 | s1 | ArgumentNode is missing PostUpdateNode. | +| C.cpp:30:10:30:11 | s2 | ArgumentNode is missing PostUpdateNode. | +| C.cpp:31:10:31:11 | s3 | ArgumentNode is missing PostUpdateNode. | +| C.cpp:32:10:32:11 | s4 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:22:25:22:31 | call to getElem | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:24:29:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:33:29:39 | 0 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:24:36:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:33:36:39 | 0 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:24:43:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:33:43:39 | 0 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:24:50:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:33:50:39 | 0 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:25:57:41 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:34:57:40 | 0 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:27:14:27:15 | s3 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:29:11:29:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:30:11:30:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:31:11:31:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:38:11:38:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:43:13:43:14 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:50:11:50:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:55:14:55:15 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:62:14:62:15 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:73:12:73:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:80:12:80:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:87:12:87:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:93:12:93:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:40:12:40:15 | this | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:44:26:44:29 | this | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:50:17:50:26 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:51:8:51:8 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:51:10:51:20 | call to getDirectly | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:56:19:56:28 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:57:8:57:8 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:57:10:57:22 | call to getIndirectly | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:62:25:62:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:63:8:63:8 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:68:21:68:30 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:69:22:69:23 | & ... | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:22:13:22:13 | 0 | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:22:16:22:16 | 0 | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:44:12:44:12 | call to a | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:45:12:45:12 | call to b | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:55:13:55:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:56:13:56:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:57:13:57:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:58:13:58:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:34:11:34:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:34:25:34:25 | 0 | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:35:14:35:23 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:36:11:36:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:36:25:36:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:34:11:34:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:34:14:34:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:35:14:35:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:36:11:36:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:36:14:36:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:39:12:39:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:40:12:40:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:41:12:41:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:42:12:42:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.ql b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.ql new file mode 100644 index 00000000000..4304a961abe --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected new file mode 100644 index 00000000000..1bbc904b3f4 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -0,0 +1,338 @@ +uniqueEnclosingCallable +uniqueTypeBound +uniqueTypeRepr +uniqueNodeLocation +| D.cpp:1:17:1:17 | o | Node should have one location but has 2. | +| by_reference.cpp:1:17:1:17 | o | Node should have one location but has 2. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +missingLocation +| Nodes without location: 4 | +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| A.cpp:9:9:9:9 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| A.cpp:14:9:14:9 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| A.cpp:31:14:31:21 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:31:14:31:21 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:31:20:31:20 | c | ArgumentNode is missing PostUpdateNode. | +| A.cpp:38:7:38:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| A.cpp:39:7:39:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| A.cpp:40:5:40:6 | cc | ArgumentNode is missing PostUpdateNode. | +| A.cpp:40:15:40:21 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:41:5:41:6 | ct | ArgumentNode is missing PostUpdateNode. | +| A.cpp:41:15:41:21 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:41:15:41:21 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:41:15:41:21 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:42:10:42:12 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:43:10:43:12 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:47:12:47:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:47:12:47:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:48:20:48:20 | c | ArgumentNode is missing PostUpdateNode. | +| A.cpp:49:10:49:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:54:12:54:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:54:12:54:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:55:5:55:5 | b | ArgumentNode is missing PostUpdateNode. | +| A.cpp:55:12:55:19 | (C *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:55:12:55:19 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:55:12:55:19 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:56:10:56:10 | b | ArgumentNode is missing PostUpdateNode. | +| A.cpp:56:10:56:17 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:10:57:32 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:11:57:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:11:57:24 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:17:57:23 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:17:57:23 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:62:13:62:19 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:62:13:62:19 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:64:17:64:18 | b1 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:64:21:64:28 | (C *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:64:21:64:28 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:64:21:64:28 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:65:10:65:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:66:10:66:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:71:13:71:19 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:71:13:71:19 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:73:21:73:22 | b1 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:73:25:73:32 | (C *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:73:25:73:32 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:73:25:73:32 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:74:10:74:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:75:10:75:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:81:17:81:18 | b1 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:81:21:81:21 | c | ArgumentNode is missing PostUpdateNode. | +| A.cpp:89:15:89:21 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:89:15:89:21 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:90:7:90:8 | b2 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:90:15:90:15 | c | ArgumentNode is missing PostUpdateNode. | +| A.cpp:98:12:98:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:99:14:99:21 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:99:14:99:21 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:101:8:101:9 | (C *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:107:12:107:16 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:116:12:116:19 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:116:12:116:19 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:120:12:120:16 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:126:5:126:5 | b | ArgumentNode is missing PostUpdateNode. | +| A.cpp:126:12:126:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:126:12:126:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:130:12:130:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:130:12:130:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:131:8:131:8 | b | ArgumentNode is missing PostUpdateNode. | +| A.cpp:132:10:132:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:142:14:142:20 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:142:14:142:20 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:143:25:143:31 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:143:25:143:31 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:150:12:150:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:150:12:150:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:151:12:151:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:151:12:151:24 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:151:18:151:18 | b | ArgumentNode is missing PostUpdateNode. | +| A.cpp:151:21:151:21 | call to r | ArgumentNode is missing PostUpdateNode. | +| A.cpp:152:10:152:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:153:10:153:16 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:154:10:154:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:159:12:159:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:159:12:159:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:18:160:60 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:18:160:60 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:29:160:29 | b | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:32:160:59 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:32:160:59 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:43:160:49 | (B *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:52:160:58 | (MyList *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:161:18:161:40 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:161:18:161:40 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:161:29:161:35 | (B *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:161:38:161:39 | l1 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:162:18:162:40 | Constant | ArgumentNode is missing PostUpdateNode. | +| A.cpp:162:18:162:40 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:162:29:162:35 | (B *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:162:38:162:39 | l2 | ArgumentNode is missing PostUpdateNode. | +| A.cpp:163:10:163:17 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:164:10:164:23 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:165:10:165:29 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:166:10:166:35 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| A.cpp:169:12:169:18 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| B.cpp:6:15:6:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| B.cpp:7:16:7:35 | Constant | ArgumentNode is missing PostUpdateNode. | +| B.cpp:7:16:7:35 | new | ArgumentNode is missing PostUpdateNode. | +| B.cpp:7:25:7:25 | e | ArgumentNode is missing PostUpdateNode. | +| B.cpp:7:28:7:34 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | +| B.cpp:8:16:8:27 | Constant | ArgumentNode is missing PostUpdateNode. | +| B.cpp:8:16:8:27 | new | ArgumentNode is missing PostUpdateNode. | +| B.cpp:8:25:8:26 | b1 | ArgumentNode is missing PostUpdateNode. | +| B.cpp:9:10:9:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| B.cpp:10:10:10:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| B.cpp:15:15:15:27 | Constant | ArgumentNode is missing PostUpdateNode. | +| B.cpp:16:16:16:38 | Constant | ArgumentNode is missing PostUpdateNode. | +| B.cpp:16:16:16:38 | new | ArgumentNode is missing PostUpdateNode. | +| B.cpp:16:28:16:34 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | +| B.cpp:16:37:16:37 | e | ArgumentNode is missing PostUpdateNode. | +| B.cpp:17:16:17:27 | Constant | ArgumentNode is missing PostUpdateNode. | +| B.cpp:17:16:17:27 | new | ArgumentNode is missing PostUpdateNode. | +| B.cpp:17:25:17:26 | b1 | ArgumentNode is missing PostUpdateNode. | +| B.cpp:18:10:18:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| B.cpp:19:10:19:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| C.cpp:18:12:18:18 | Constant | ArgumentNode is missing PostUpdateNode. | +| C.cpp:18:12:18:18 | new | ArgumentNode is missing PostUpdateNode. | +| C.cpp:19:5:19:5 | c | ArgumentNode is missing PostUpdateNode. | +| C.cpp:22:12:22:21 | Constant | ArgumentNode is missing PostUpdateNode. | +| C.cpp:24:16:24:25 | Constant | ArgumentNode is missing PostUpdateNode. | +| C.cpp:32:10:32:11 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| D.cpp:22:10:22:11 | b2 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:22:10:22:33 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| D.cpp:22:14:22:20 | call to getBox1 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:28:15:28:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:15:29:41 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:15:29:41 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:24:29:40 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:24:29:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:33:29:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | +| D.cpp:31:14:31:14 | b | ArgumentNode is missing PostUpdateNode. | +| D.cpp:35:15:35:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:15:36:41 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:15:36:41 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:24:36:40 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:24:36:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:33:36:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | +| D.cpp:37:8:37:10 | box | ArgumentNode is missing PostUpdateNode. | +| D.cpp:37:21:37:21 | e | ArgumentNode is missing PostUpdateNode. | +| D.cpp:38:14:38:14 | b | ArgumentNode is missing PostUpdateNode. | +| D.cpp:42:15:42:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:15:43:41 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:15:43:41 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:24:43:40 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:24:43:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:33:43:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | +| D.cpp:44:5:44:5 | b | ArgumentNode is missing PostUpdateNode. | +| D.cpp:45:14:45:14 | b | ArgumentNode is missing PostUpdateNode. | +| D.cpp:49:15:49:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:15:50:41 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:15:50:41 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:24:50:40 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:24:50:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:33:50:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | +| D.cpp:51:5:51:5 | b | ArgumentNode is missing PostUpdateNode. | +| D.cpp:51:8:51:14 | call to getBox1 | ArgumentNode is missing PostUpdateNode. | +| D.cpp:51:27:51:27 | e | ArgumentNode is missing PostUpdateNode. | +| D.cpp:52:14:52:14 | b | ArgumentNode is missing PostUpdateNode. | +| D.cpp:56:15:56:24 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:16:57:42 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:16:57:42 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:25:57:41 | Constant | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:25:57:41 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:34:57:40 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | +| D.cpp:64:10:64:28 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| E.cpp:21:18:21:23 | buffer | ArgumentNode is missing PostUpdateNode. | +| E.cpp:28:21:28:23 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| E.cpp:29:21:29:29 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| E.cpp:30:21:30:33 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| E.cpp:31:10:31:12 | raw | ArgumentNode is missing PostUpdateNode. | +| E.cpp:32:13:32:18 | buffer | ArgumentNode is missing PostUpdateNode. | +| E.cpp:33:18:33:19 | & ... | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:25:17:25:19 | & ... | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:26:19:26:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:27:14:27:15 | s3 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:29:11:29:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:30:11:30:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:31:11:31:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:38:11:38:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:43:13:43:14 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:50:11:50:12 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:55:14:55:15 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:62:14:62:15 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:73:12:73:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:80:12:80:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:87:12:87:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| aliasing.cpp:93:12:93:13 | m1 | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:20:5:20:8 | this | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:20:23:20:27 | value | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:24:19:24:22 | this | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:24:25:24:29 | value | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:40:12:40:15 | this | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:44:26:44:29 | this | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:50:3:50:3 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:50:17:50:26 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:51:8:51:8 | (const S)... | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:51:10:51:20 | call to getDirectly | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:56:3:56:3 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:56:19:56:28 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:57:8:57:8 | (const S)... | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:57:10:57:22 | call to getIndirectly | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:62:3:62:3 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:62:25:62:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:63:8:63:8 | (const S)... | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:68:17:68:18 | & ... | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:68:21:68:30 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:69:22:69:23 | (const S *)... | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:22:11:22:17 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:22:13:22:13 | 0 | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:22:16:22:16 | 0 | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:44:10:44:10 | f | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:44:12:44:12 | call to a | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:45:10:45:10 | f | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:45:12:45:12 | call to b | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:50:7:50:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:51:7:51:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:52:7:52:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:53:7:53:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:55:6:55:6 | f | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:55:13:55:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:56:6:56:6 | f | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:56:13:56:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:57:6:57:6 | f | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:57:13:57:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:58:6:58:6 | f | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:58:13:58:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:61:7:61:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:64:7:64:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:67:7:67:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| complex.cpp:70:7:70:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:28:10:28:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:29:10:29:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:34:9:34:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:34:11:34:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:34:25:34:25 | 0 | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:35:9:35:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:35:14:35:23 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:36:9:36:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:36:11:36:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:36:25:36:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:37:9:37:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:40:9:40:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:43:9:43:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:46:9:46:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| constructors.cpp:49:9:49:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:28:10:28:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:29:10:29:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:34:9:34:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:34:11:34:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:34:14:34:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:35:9:35:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:35:14:35:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:36:9:36:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:36:11:36:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:36:14:36:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:37:9:37:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:39:5:39:5 | f | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:39:12:39:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:40:5:40:5 | g | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:40:12:40:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:41:5:41:5 | h | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:41:12:41:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:42:5:42:5 | h | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:42:12:42:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:45:9:45:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:48:9:48:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:51:9:51:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| simple.cpp:54:9:54:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:15:12:15:12 | a | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:16:12:16:12 | b | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:22:11:22:11 | a | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:23:11:23:11 | b | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:24:10:24:12 | & ... | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:31:23:31:23 | a | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:32:23:32:23 | b | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:33:25:33:25 | a | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:34:25:34:25 | b | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:36:10:36:24 | & ... | ArgumentNode is missing PostUpdateNode. | +| struct_init.c:46:16:46:24 | pointerAB | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.ql b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.ql new file mode 100644 index 00000000000..6d9f8e314f7 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected new file mode 100644 index 00000000000..0664248b431 --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected @@ -0,0 +1,286 @@ +uniqueEnclosingCallable +| enum.c:2:6:2:6 | 1 | Node should have one enclosing callable but has 0. | +| enum.c:2:6:2:10 | ... + ... | Node should have one enclosing callable but has 0. | +| enum.c:2:10:2:10 | 1 | Node should have one enclosing callable but has 0. | +| misc.c:11:17:11:17 | 1 | Node should have one enclosing callable but has 0. | +| misc.c:11:17:11:21 | ... + ... | Node should have one enclosing callable but has 0. | +| misc.c:11:21:11:21 | 2 | Node should have one enclosing callable but has 0. | +| misc.c:210:24:210:24 | 0 | Node should have one enclosing callable but has 0. | +| misc.c:210:24:210:28 | ... + ... | Node should have one enclosing callable but has 0. | +| misc.c:210:28:210:28 | 1 | Node should have one enclosing callable but has 0. | +uniqueTypeBound +| bad_asts.cpp:19:10:19:10 | constructor init of field x [post-this] | Node should have one type bound but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field x [pre-this] | Node should have one type bound but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [post-this] | Node should have one type bound but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [pre-this] | Node should have one type bound but has 0. | +| cpp17.cpp:15:5:15:45 | call to unknown function | Node should have one type bound but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [post-this] | Node should have one type bound but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [pre-this] | Node should have one type bound but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [post-this] | Node should have one type bound but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [pre-this] | Node should have one type bound but has 0. | +uniqueTypeRepr +| bad_asts.cpp:19:10:19:10 | constructor init of field x [post-this] | Node should have one type representation but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field x [pre-this] | Node should have one type representation but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [post-this] | Node should have one type representation but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [pre-this] | Node should have one type representation but has 0. | +| cpp17.cpp:15:5:15:45 | call to unknown function | Node should have one type representation but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [post-this] | Node should have one type representation but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [pre-this] | Node should have one type representation but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [post-this] | Node should have one type representation but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [pre-this] | Node should have one type representation but has 0. | +uniqueNodeLocation +| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | +| cpp11.cpp:82:17:82:55 | call to Val | Node should have one location but has 2. | +| cpp11.cpp:82:17:82:55 | call to Val | Node should have one location but has 2. | +| duff.c:2:12:2:12 | i | Node should have one location but has 4. | +| duff.c:2:12:2:12 | x | Node should have one location but has 4. | +| file://:0:0:0:0 | call to PolymorphicBase | Node should have one location but has 2. | +| file://:0:0:0:0 | call to PolymorphicDerived | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Val | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Val | Node should have one location but has 2. | +| file://:0:0:0:0 | call to exn1 | Node should have one location but has 2. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | +| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | +| ir.cpp:850:19:850:19 | call to PolymorphicBase | Node should have one location but has 2. | +| ir.cpp:851:22:851:22 | call to PolymorphicDerived | Node should have one location but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| try_catch.cpp:13:5:13:16 | call to exn1 | Node should have one location but has 2. | +missingLocation +| Nodes without location: 2 | +uniqueNodeToString +| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | i | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | x | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | i | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | x | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | i | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | x | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | i | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | x | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | i | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| CPP-309.cpp:7:5:7:20 | | ArgumentNode is missing PostUpdateNode. | +| CPP-309.cpp:7:9:7:9 | 2 | ArgumentNode is missing PostUpdateNode. | +| CPP-309.cpp:7:12:7:12 | 3 | ArgumentNode is missing PostUpdateNode. | +| CPP-309.cpp:11:13:11:13 | 1 | ArgumentNode is missing PostUpdateNode. | +| VacuousDestructorCall.cpp:10:18:10:18 | i | ArgumentNode is missing PostUpdateNode. | +| abortingfunctions.cpp:45:13:45:13 | 0 | ArgumentNode is missing PostUpdateNode. | +| abortingfunctions.cpp:45:16:45:16 | 0 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:14:16:36 | | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:18:16:19 | 11 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:22:16:23 | 22 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:30:16:31 | 33 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:34:16:35 | 44 | ArgumentNode is missing PostUpdateNode. | +| bad_asts.cpp:16:25:16:25 | 1 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:8:32:8:32 | 0 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:8:35:8:37 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:8:40:8:40 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:10:20:10:26 | ... != ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:20:33:20:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:21:33:21:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:21:38:21:38 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:22:34:22:36 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:22:39:22:39 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:28:31:28:38 | ... == ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:34:34:34:34 | x | ArgumentNode is missing PostUpdateNode. | +| builtin.c:39:25:39:27 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:39:30:39:30 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:39:33:39:33 | 1 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:43:26:43:28 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:43:37:43:37 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:45:33:45:41 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:47:24:47:30 | Hello | ArgumentNode is missing PostUpdateNode. | +| builtin.c:47:33:47:35 | 101 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:47:38:47:38 | 5 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:51:41:51:43 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:51:46:51:46 | 0 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:54:41:54:41 | 0 | ArgumentNode is missing PostUpdateNode. | +| builtin.cpp:14:40:14:44 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| builtin.cpp:15:31:15:35 | * ... | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:16:20:16:20 | x | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:26:24:26:24 | x | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:41:23:41:23 | x | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:23:48:24 | - ... | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:35:48:36 | - ... | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:53:48:53 | x | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:9:30:13 | call to C1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:12:30:12 | 1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:18:30:22 | call to C1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:21:30:21 | 2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:9:33:13 | call to C1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:12:33:12 | 3 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:18:33:22 | call to C1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:21:33:21 | 3 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:9:39:13 | call to C2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:12:39:12 | 1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:18:39:22 | call to C2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:21:39:21 | 2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:9:42:13 | call to C2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:12:42:12 | 3 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:18:42:22 | call to C2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:21:42:21 | 3 | ArgumentNode is missing PostUpdateNode. | +| constructorinitializer.cpp:8:6:8:10 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| constructorinitializer.cpp:8:13:8:17 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:28:21:28:21 | (__end) | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:5:77:17 | unaryFunction | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:19:77:21 | arg | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:19:77:21 | arg | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:19:77:21 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:11:82:14 | arg2 | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:11:82:14 | arg2 | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:11:82:14 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:17:82:55 | [...](...){...} | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:17:82:55 | [...](...){...} | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:30:82:52 | arg1 | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:45:82:48 | arg1 | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:45:82:48 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:51:82:51 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:51:82:51 | x | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:51:82:51 | x | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:12:88:22 | doSomething | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:25:88:30 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:29:88:29 | 1 | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:33:88:38 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:37:88:37 | 2 | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:5:15:45 | | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:38:15:41 | args | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:38:15:41 | args | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:38:15:41 | p#2 | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:19:13:19:13 | 1 | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:19:16:19:16 | 2 | ArgumentNode is missing PostUpdateNode. | +| destructors.cpp:52:14:52:16 | ref | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:377:16:377:16 | x | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:377:19:377:19 | y | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:381:32:381:32 | x | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:381:35:381:35 | y | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:552:16:552:16 | 5 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:585:20:585:26 | %d %s | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:585:29:585:29 | 1 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:585:32:585:39 | string | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:617:15:617:21 | hello | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:619:24:619:29 | test | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:623:5:623:5 | r | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:624:5:624:5 | p | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:625:5:625:5 | s | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:653:38:653:38 | 0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:654:40:654:40 | 1 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:655:32:655:32 | 2 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:662:13:662:18 | test | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:700:7:700:7 | 5 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:709:14:709:14 | x | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:709:17:709:17 | y | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:721:41:721:47 | 0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:721:50:721:52 | 111 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:731:32:731:46 | String object | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:736:18:736:18 | s | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:745:8:745:8 | base_s | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:754:8:754:8 | * ... | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:754:8:754:8 | middle_s | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:763:8:763:8 | * ... | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:763:8:763:8 | derived_s | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:808:7:808:7 | m | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:809:7:809:13 | call to Base | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:809:13:809:13 | m | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:810:7:810:26 | call to Base | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:810:25:810:25 | m | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:816:16:816:16 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:817:28:817:28 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:822:7:822:7 | d | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:823:7:823:13 | call to Base | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:823:13:823:13 | d | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:824:7:824:26 | call to Base | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:824:25:824:25 | d | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:830:17:830:17 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:831:29:831:29 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:868:10:868:11 | | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:942:3:942:15 | | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:942:7:942:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:945:3:945:27 | | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:945:7:945:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:945:20:945:26 | hello | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:947:3:947:25 | | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:947:7:947:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:947:25:947:25 | 128 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:953:3:953:18 | | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:953:7:953:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:956:3:956:27 | | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:956:7:956:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:956:28:956:28 | 128 | ArgumentNode is missing PostUpdateNode. | +| membercallexpr_args.cpp:10:10:10:14 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| membercallexpr_args.cpp:10:17:10:21 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| misc.c:83:14:83:14 | i | ArgumentNode is missing PostUpdateNode. | +| misc.c:83:17:83:17 | j | ArgumentNode is missing PostUpdateNode. | +| misc.c:84:16:84:16 | i | ArgumentNode is missing PostUpdateNode. | +| misc.c:84:19:84:19 | j | ArgumentNode is missing PostUpdateNode. | +| misc.c:147:16:147:16 | i | ArgumentNode is missing PostUpdateNode. | +| misc.c:147:19:147:19 | j | ArgumentNode is missing PostUpdateNode. | +| misc.c:228:31:228:40 | global_int | ArgumentNode is missing PostUpdateNode. | +| misc.c:229:32:229:41 | global_int | ArgumentNode is missing PostUpdateNode. | +| misc.c:230:27:230:36 | global_int | ArgumentNode is missing PostUpdateNode. | +| misc.c:231:29:231:38 | global_int | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:13:21:13:35 | Hello, world! | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:14:21:14:21 | 0 | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:28:26:28:28 | 256 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:11:12:11:14 | 101 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:14:16:14:18 | 102 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:18:16:18:18 | 103 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:21:16:21:18 | 104 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:24:12:24:14 | 105 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:28:12:28:14 | 101 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:31:16:31:18 | 106 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:35:16:35:18 | 107 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:38:16:38:18 | 108 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:41:12:41:14 | 109 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:48:10:48:12 | 201 | ArgumentNode is missing PostUpdateNode. | +| newexpr.cpp:8:8:8:12 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| newexpr.cpp:8:15:8:19 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| no_dynamic_init.cpp:5:12:5:35 | Goodbye cruel world.\n | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:19:15:19:22 | | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:20:18:20:30 | | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:21:18:21:34 | | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:26:31:26:53 | | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:8:12:8:21 | Got %d\n | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:8:24:8:24 | i | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:19:7:19:7 | 3 | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:21:7:21:7 | 4 | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:23:46:23:50 | 0 | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:24:42:24:45 | 1 | ArgumentNode is missing PostUpdateNode. | +| staticlocals.cpp:27:27:27:29 | two | ArgumentNode is missing PostUpdateNode. | +| staticlocals.cpp:28:27:28:27 | 2 | ArgumentNode is missing PostUpdateNode. | +| staticmembercallexpr_args.cpp:10:9:10:13 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| staticmembercallexpr_args.cpp:10:16:10:20 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| stmt_expr.cpp:13:18:13:18 | 1 | ArgumentNode is missing PostUpdateNode. | +| stmt_expr.cpp:30:20:30:20 | 3 | ArgumentNode is missing PostUpdateNode. | +| vla.c:5:27:5:33 | access to array | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.ql b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.ql new file mode 100644 index 00000000000..4304a961abe --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected new file mode 100644 index 00000000000..19877a98a30 --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -0,0 +1,1105 @@ +uniqueEnclosingCallable +uniqueTypeBound +| break_labels.c:13:5:13:18 | VariableAddress | Node should have one type bound but has 2. | +| break_labels.c:13:12:13:17 | Store | Node should have one type bound but has 2. | +| enum.c:6:2:6:10 | VariableAddress | Node should have one type bound but has 2. | +| enum.c:6:9:6:9 | Store | Node should have one type bound but has 2. | +| parameterinitializer.cpp:4:5:4:13 | VariableAddress | Node should have one type bound but has 2. | +| parameterinitializer.cpp:4:12:4:12 | Store | Node should have one type bound but has 2. | +uniqueTypeRepr +uniqueNodeLocation +| aggregateinitializer.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| allocators.cpp:14:5:14:8 | AliasedDefinition | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | AliasedUse | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | Chi | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | EnterFunction | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | ExitFunction | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | InitializeNonLocal | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | ReturnValue | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | UnmodeledDefinition | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | UnmodeledUse | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | VariableAddress | Node should have one location but has 4. | +| array_delete.cpp:5:6:5:6 | AliasedDefinition | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | AliasedUse | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | Chi | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | EnterFunction | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | ExitFunction | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | InitializeNonLocal | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | ReturnVoid | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | UnmodeledDefinition | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | UnmodeledUse | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| break_labels.c:2:5:2:5 | AliasedDefinition | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | AliasedUse | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | Chi | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | EnterFunction | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | ExitFunction | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | InitializeNonLocal | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | ReturnVoid | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | UnmodeledDefinition | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | UnmodeledUse | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | Unreached | Node should have one location but has 20. | +| break_labels.c:2:11:2:11 | VariableAddress | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | +| conditional_destructors.cpp:29:6:29:7 | AliasedDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | AliasedUse | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | Chi | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | EnterFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | ExitFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | ReturnVoid | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | UnmodeledUse | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | AliasedDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | AliasedUse | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | Chi | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | EnterFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | ExitFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | ReturnVoid | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | UnmodeledUse | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | Unreached | Node should have one location but has 2. | +| constmemberaccess.cpp:3:7:3:7 | x | Node should have one location but has 2. | +| constmemberaccess.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| constructorinitializer.cpp:3:9:3:9 | i | Node should have one location but has 2. | +| constructorinitializer.cpp:3:9:3:9 | x | Node should have one location but has 2. | +| constructorinitializer.cpp:3:16:3:16 | j | Node should have one location but has 2. | +| constructorinitializer.cpp:3:16:3:16 | y | Node should have one location but has 2. | +| constructorinitializer.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | AliasedDefinition | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | AliasedUse | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | Chi | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | EnterFunction | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | ExitFunction | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | ReturnVoid | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | UnmodeledUse | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | AliasedDefinition | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | AliasedUse | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | Chi | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | EnterFunction | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | ExitFunction | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | InitializeNonLocal | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | ReturnVoid | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | UnmodeledUse | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| dostmt.c:8:6:8:18 | AliasedDefinition | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | AliasedUse | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | Chi | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | EnterFunction | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | ExitFunction | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | InitializeNonLocal | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | ReturnVoid | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | UnmodeledDefinition | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | UnmodeledUse | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | Unreached | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | AliasedDefinition | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | AliasedUse | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | Chi | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | EnterFunction | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | ExitFunction | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | InitializeNonLocal | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | ReturnVoid | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | UnmodeledDefinition | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | UnmodeledUse | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | Unreached | Node should have one location but has 4. | +| dostmt.c:25:6:25:18 | AliasedDefinition | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | Chi | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | EnterFunction | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | InitializeNonLocal | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | UnmodeledDefinition | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | Unreached | Node should have one location but has 2. | +| dostmt.c:32:6:32:11 | AliasedDefinition | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | AliasedUse | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | Chi | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | EnterFunction | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | ExitFunction | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | InitializeNonLocal | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | ReturnVoid | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | UnmodeledDefinition | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | UnmodeledUse | Node should have one location but has 4. | +| duff.c:2:6:2:6 | AliasedDefinition | Node should have one location but has 20. | +| duff.c:2:6:2:6 | AliasedUse | Node should have one location but has 20. | +| duff.c:2:6:2:6 | Chi | Node should have one location but has 20. | +| duff.c:2:6:2:6 | EnterFunction | Node should have one location but has 20. | +| duff.c:2:6:2:6 | ExitFunction | Node should have one location but has 20. | +| duff.c:2:6:2:6 | InitializeNonLocal | Node should have one location but has 20. | +| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | +| duff.c:2:6:2:6 | ReturnVoid | Node should have one location but has 20. | +| duff.c:2:6:2:6 | UnmodeledDefinition | Node should have one location but has 20. | +| duff.c:2:6:2:6 | UnmodeledUse | Node should have one location but has 20. | +| duff.c:2:6:2:6 | Unreached | Node should have one location but has 20. | +| duff.c:2:12:2:12 | VariableAddress | Node should have one location but has 4. | +| duff.c:2:12:2:12 | i | Node should have one location but has 4. | +| duff.c:2:12:2:12 | i | Node should have one location but has 4. | +| duff.c:2:12:2:12 | x | Node should have one location but has 4. | +| duff.c:2:12:2:12 | x | Node should have one location but has 4. | +| dummyblock.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| enum.c:5:5:5:5 | AliasedDefinition | Node should have one location but has 20. | +| enum.c:5:5:5:5 | AliasedUse | Node should have one location but has 20. | +| enum.c:5:5:5:5 | Chi | Node should have one location but has 20. | +| enum.c:5:5:5:5 | EnterFunction | Node should have one location but has 20. | +| enum.c:5:5:5:5 | ExitFunction | Node should have one location but has 20. | +| enum.c:5:5:5:5 | InitializeNonLocal | Node should have one location but has 20. | +| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | +| enum.c:5:5:5:5 | ReturnVoid | Node should have one location but has 20. | +| enum.c:5:5:5:5 | UnmodeledDefinition | Node should have one location but has 20. | +| enum.c:5:5:5:5 | UnmodeledUse | Node should have one location but has 20. | +| enum.c:5:5:5:5 | Unreached | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| fieldaccess.cpp:3:7:3:7 | x | Node should have one location but has 2. | +| fieldaccess.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| file://:0:0:0:0 | InitializeIndirection | Node should have one location but has 0. | +| file://:0:0:0:0 | Load | Node should have one location but has 0. | +| file://:0:0:0:0 | ReturnIndirection | Node should have one location but has 0. | +| file://:0:0:0:0 | VariableAddress | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#3 | Node should have one location but has 0. | +| forstmt.cpp:1:6:1:7 | AliasedDefinition | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | AliasedUse | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | Chi | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | EnterFunction | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | ExitFunction | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | InitializeNonLocal | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | ReturnVoid | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | UnmodeledDefinition | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | UnmodeledUse | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | AliasedDefinition | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | AliasedUse | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | Chi | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | EnterFunction | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | ExitFunction | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | InitializeNonLocal | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | ReturnVoid | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | UnmodeledDefinition | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | UnmodeledUse | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | Unreached | Node should have one location but has 2. | +| ifelsestmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | UnmodeledUse | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | AliasedDefinition | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | AliasedUse | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | Chi | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | EnterFunction | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | ExitFunction | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | ReturnVoid | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | UnmodeledUse | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | Unreached | Node should have one location but has 3. | +| ifelsestmt.c:19:6:19:18 | AliasedDefinition | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | AliasedUse | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | Chi | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | EnterFunction | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | ExitFunction | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | ReturnVoid | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | UnmodeledUse | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | Unreached | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | AliasedDefinition | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | AliasedUse | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | Chi | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | EnterFunction | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | ExitFunction | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | ReturnVoid | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | UnmodeledUse | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | Unreached | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | AliasedDefinition | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | AliasedUse | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | Chi | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | EnterFunction | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | ExitFunction | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | InitializeNonLocal | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | ReturnVoid | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | UnmodeledDefinition | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | UnmodeledUse | Node should have one location but has 4. | +| ifelsestmt.c:37:17:37:17 | VariableAddress | Node should have one location but has 2. | +| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | +| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | VariableAddress | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | +| ifstmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | UnmodeledUse | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | AliasedDefinition | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | AliasedUse | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | Chi | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | EnterFunction | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | ExitFunction | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | ReturnVoid | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | UnmodeledUse | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | Unreached | Node should have one location but has 3. | +| ifstmt.c:14:6:14:18 | AliasedDefinition | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | AliasedUse | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | Chi | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | EnterFunction | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | ExitFunction | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | ReturnVoid | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | UnmodeledUse | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | Unreached | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | AliasedDefinition | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | AliasedUse | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | Chi | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | EnterFunction | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | ExitFunction | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | ReturnVoid | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | UnmodeledUse | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | Unreached | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | AliasedDefinition | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | AliasedUse | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | Chi | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | EnterFunction | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | ExitFunction | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | InitializeNonLocal | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | ReturnVoid | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | UnmodeledDefinition | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | UnmodeledUse | Node should have one location but has 4. | +| ifstmt.c:27:17:27:17 | VariableAddress | Node should have one location but has 2. | +| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | +| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | VariableAddress | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | +| initializer.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| membercallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| membercallexpr_args.cpp:3:6:3:6 | d | Node should have one location but has 2. | +| membercallexpr_args.cpp:4:14:4:14 | x | Node should have one location but has 2. | +| membercallexpr_args.cpp:4:21:4:21 | y | Node should have one location but has 2. | +| membercallexpr_args.cpp:7:6:7:6 | AliasedDefinition | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | AliasedUse | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | Chi | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | EnterFunction | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | ExitFunction | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | ReturnVoid | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | UnmodeledUse | Node should have one location but has 14. | +| newexpr.cpp:3:9:3:9 | i | Node should have one location but has 2. | +| newexpr.cpp:3:9:3:9 | x | Node should have one location but has 2. | +| newexpr.cpp:3:16:3:16 | j | Node should have one location but has 2. | +| newexpr.cpp:3:16:3:16 | y | Node should have one location but has 2. | +| newexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| no_dynamic_init.cpp:9:5:9:8 | AliasedDefinition | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | AliasedUse | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | Chi | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | EnterFunction | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | ExitFunction | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | InitializeNonLocal | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | ReturnValue | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | UnmodeledUse | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | VariableAddress | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:12:1:12 | VariableAddress | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| nonmembercallexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | Chi | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 2. | +| nonmembercallexpr.c:3:6:3:6 | AliasedDefinition | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | AliasedUse | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | Chi | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | EnterFunction | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | ExitFunction | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | InitializeNonLocal | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | ReturnVoid | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | UnmodeledUse | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | Unreached | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | AliasedDefinition | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | AliasedUse | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | Chi | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | EnterFunction | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | ExitFunction | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | InitializeNonLocal | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | ReturnVoid | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | UnmodeledUse | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | Unreached | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| parameterinitializer.cpp:18:5:18:8 | AliasedDefinition | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | AliasedUse | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | Chi | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | EnterFunction | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | ExitFunction | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | InitializeNonLocal | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | ReturnValue | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | UnmodeledUse | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | VariableAddress | Node should have one location but has 4. | +| pmcallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| questionexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| revsubscriptexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | Chi | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 2. | +| staticmembercallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:3:6:3:6 | d | Node should have one location but has 2. | +| staticmembercallexpr_args.cpp:4:21:4:21 | x | Node should have one location but has 2. | +| staticmembercallexpr_args.cpp:4:28:4:28 | y | Node should have one location but has 2. | +| staticmembercallexpr_args.cpp:7:6:7:6 | AliasedDefinition | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | AliasedUse | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | Chi | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | EnterFunction | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | ExitFunction | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | ReturnVoid | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledUse | Node should have one location but has 14. | +| stream_it.cpp:16:5:16:8 | AliasedDefinition | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | AliasedUse | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | Chi | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | EnterFunction | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | ExitFunction | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | InitializeNonLocal | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | ReturnValue | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | UnmodeledDefinition | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | UnmodeledUse | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | VariableAddress | Node should have one location but has 4. | +| subscriptexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| switchstmt.c:1:12:1:12 | VariableAddress | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| tinyforstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| whilestmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | UnmodeledDefinition | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | UnmodeledUse | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | AliasedDefinition | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | AliasedUse | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | Chi | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | EnterFunction | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | ExitFunction | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | InitializeNonLocal | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | ReturnVoid | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | UnmodeledDefinition | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | UnmodeledUse | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | Unreached | Node should have one location but has 3. | +| whilestmt.c:15:6:15:18 | AliasedDefinition | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | AliasedUse | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | Chi | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | EnterFunction | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | ExitFunction | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | InitializeNonLocal | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | ReturnVoid | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | UnmodeledDefinition | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | UnmodeledUse | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | Unreached | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | AliasedDefinition | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | AliasedUse | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | Chi | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | EnterFunction | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | ExitFunction | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | InitializeNonLocal | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | ReturnVoid | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | UnmodeledDefinition | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | UnmodeledUse | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | Unreached | Node should have one location but has 4. | +| whilestmt.c:32:6:32:18 | AliasedDefinition | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | Chi | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | EnterFunction | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | InitializeNonLocal | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | UnmodeledDefinition | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | Unreached | Node should have one location but has 2. | +| whilestmt.c:39:6:39:11 | AliasedDefinition | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | AliasedUse | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | Chi | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | EnterFunction | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | ExitFunction | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | InitializeNonLocal | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | ReturnVoid | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | UnmodeledDefinition | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | UnmodeledUse | Node should have one location but has 4. | +missingLocation +| Nodes without location: 30 | +uniqueNodeToString +| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | i | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | x | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | i | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | x | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | i | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | x | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:9:3:9 | i | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:9:3:9 | x | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:16:3:16 | j | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:16:3:16 | y | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | i | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | x | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | i | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | x | Node should have one toString but has 2. | +| newexpr.cpp:3:9:3:9 | i | Node should have one toString but has 2. | +| newexpr.cpp:3:9:3:9 | x | Node should have one toString but has 2. | +| newexpr.cpp:3:16:3:16 | j | Node should have one toString but has 2. | +| newexpr.cpp:3:16:3:16 | y | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| CPP-309.cpp:7:5:7:20 | Constant | ArgumentNode is missing PostUpdateNode. | +| CPP-309.cpp:7:9:7:9 | 2 | ArgumentNode is missing PostUpdateNode. | +| CPP-309.cpp:7:12:7:12 | 3 | ArgumentNode is missing PostUpdateNode. | +| CPP-309.cpp:11:13:11:13 | 1 | ArgumentNode is missing PostUpdateNode. | +| VacuousDestructorCall.cpp:10:18:10:18 | i | ArgumentNode is missing PostUpdateNode. | +| VacuousDestructorCall.cpp:10:21:10:22 | & ... | ArgumentNode is missing PostUpdateNode. | +| abortingfunctions.cpp:45:13:45:13 | 0 | ArgumentNode is missing PostUpdateNode. | +| abortingfunctions.cpp:45:16:45:16 | 0 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:14:16:36 | Constant | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:14:16:36 | new | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:18:16:19 | 11 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:22:16:23 | 22 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:30:16:31 | 33 | ArgumentNode is missing PostUpdateNode. | +| allocators.cpp:16:34:16:35 | 44 | ArgumentNode is missing PostUpdateNode. | +| bad_asts.cpp:16:5:16:5 | s | ArgumentNode is missing PostUpdateNode. | +| bad_asts.cpp:16:25:16:25 | 1 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:8:32:8:32 | 0 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:8:35:8:37 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:8:40:8:40 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:10:20:10:26 | (bool)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:20:33:20:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:21:33:21:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:21:38:21:38 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:22:34:22:36 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:22:39:22:39 | y | ArgumentNode is missing PostUpdateNode. | +| builtin.c:28:31:28:38 | ... == ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:34:22:34:31 | (volatile void *)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:34:34:34:34 | x | ArgumentNode is missing PostUpdateNode. | +| builtin.c:39:25:39:27 | (unsigned int)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:39:30:39:30 | (unsigned int)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:39:33:39:33 | (unsigned int)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:39:36:39:45 | & ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:43:26:43:28 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:43:31:43:37 | (long)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:43:40:43:49 | & ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:45:33:45:41 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:47:24:47:30 | (const void *)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:47:33:47:35 | 101 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:47:38:47:38 | (unsigned long)... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:51:29:51:38 | & ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:51:41:51:43 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:51:46:51:46 | 0 | ArgumentNode is missing PostUpdateNode. | +| builtin.c:54:28:54:38 | & ... | ArgumentNode is missing PostUpdateNode. | +| builtin.c:54:41:54:41 | 0 | ArgumentNode is missing PostUpdateNode. | +| builtin.cpp:10:24:10:24 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| builtin.cpp:14:40:14:44 | (unsigned long)... | ArgumentNode is missing PostUpdateNode. | +| builtin.cpp:15:31:15:35 | * ... | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:3:13:3:22 | Constant | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:16:6:16:20 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:16:20:16:20 | x | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:26:10:26:24 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:26:24:26:24 | x | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:41:9:41:23 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:41:23:41:23 | x | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:16:48:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:23:48:24 | - ... | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:27:48:31 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:35:48:36 | - ... | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:39:48:53 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| condition_decls.cpp:48:53:48:53 | x | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:9:30:13 | (const C1)... | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:12:30:12 | 1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:18:30:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:30:21:30:21 | 2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:9:33:13 | (const C1)... | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:12:33:12 | 3 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:18:33:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:33:21:33:21 | 3 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:9:39:13 | (const C2)... | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:12:39:12 | 1 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:18:39:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:39:21:39:21 | 2 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:9:42:13 | (const C2)... | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:12:42:12 | 3 | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:18:42:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| conditional_destructors.cpp:42:21:42:21 | 3 | ArgumentNode is missing PostUpdateNode. | +| constructorinitializer.cpp:8:4:8:4 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| constructorinitializer.cpp:8:6:8:10 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| constructorinitializer.cpp:8:13:8:17 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:5:77:17 | (const lambda [] type at line 82, col. 17)... | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:19:77:21 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:19:77:21 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:11:82:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:11:82:14 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:17:82:55 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:17:82:55 | [...](...){...} | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:45:82:48 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:45:82:48 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:51:82:51 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:82:51:82:51 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:12:88:22 | doSomething | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:25:88:30 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:29:88:29 | 1 | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:33:88:38 | call to Val | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:88:37:88:37 | 2 | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:5:15:45 | Constant | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:5:15:45 | new | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:19:15:21 | ptr | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:38:15:41 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:15:38:15:41 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:19:10:19:10 | p | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:19:13:19:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| cpp17.cpp:19:16:19:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| defconstructornewexpr.cpp:4:2:4:6 | Constant | ArgumentNode is missing PostUpdateNode. | +| defdestructordeleteexpr.cpp:4:9:4:15 | Constant | ArgumentNode is missing PostUpdateNode. | +| deleteexpr.cpp:7:9:7:15 | Constant | ArgumentNode is missing PostUpdateNode. | +| destructors.cpp:50:9:50:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| destructors.cpp:52:14:52:16 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | & ... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | & ... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | & ... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (Base *)... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (Middle *)... | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (__begin) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (__begin) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:377:16:377:16 | x | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:377:19:377:19 | y | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:381:32:381:32 | x | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:381:35:381:35 | y | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:552:16:552:16 | 5 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:585:20:585:26 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:585:29:585:29 | 1 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:585:32:585:39 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:616:12:616:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:617:12:617:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:617:15:617:21 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:619:12:619:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:619:24:619:29 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:623:5:623:5 | (const String)... | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:624:5:624:5 | (const String *)... | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:625:5:625:5 | (const String)... | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:653:9:653:12 | this | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:653:38:653:38 | 0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:654:10:654:14 | * ... | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:654:40:654:40 | 1 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:655:32:655:32 | 2 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:662:9:662:19 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:662:13:662:18 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:663:5:663:5 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:700:7:700:7 | 5 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:709:14:709:14 | x | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:709:17:709:17 | y | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:721:41:721:47 | (void *)... | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:721:50:721:52 | 111 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:736:5:736:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:736:18:736:18 | s | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:745:8:745:8 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:748:10:748:10 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:751:3:751:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:757:12:757:12 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:757:12:757:12 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:760:3:760:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:760:3:760:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:766:13:766:13 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:766:13:766:13 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:769:3:769:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:769:3:769:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:775:15:775:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:775:15:775:15 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:778:3:778:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:778:3:778:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:784:15:784:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:784:15:784:15 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:787:3:787:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:787:3:787:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:793:15:793:15 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:796:3:796:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:796:3:796:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:796:3:796:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:796:3:796:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:800:8:800:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:801:10:801:10 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:802:11:802:11 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:808:3:808:3 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:808:7:808:7 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:809:3:809:3 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:809:7:809:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:809:13:809:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:810:3:810:3 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:810:7:810:26 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:810:25:810:25 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:816:3:816:3 | m | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:816:7:816:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:817:3:817:3 | m | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:817:7:817:29 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:822:3:822:3 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:822:7:822:7 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:823:3:823:3 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:823:7:823:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:823:13:823:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:824:3:824:3 | b | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:824:7:824:26 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:824:25:824:25 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:830:3:830:3 | d | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:830:7:830:17 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:831:3:831:3 | d | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:831:7:831:30 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:846:8:846:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:846:8:846:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:850:19:850:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:851:22:851:22 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:867:1:867:14 | this | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:868:10:868:11 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:941:3:941:9 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:942:3:942:15 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:942:7:942:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:943:3:943:11 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:944:3:944:14 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:944:3:944:14 | new | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:945:3:945:27 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:945:3:945:27 | new | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:945:7:945:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:945:20:945:26 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:946:3:946:17 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:946:18:946:18 | 128 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:947:3:947:25 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:947:7:947:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:947:25:947:25 | 128 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:951:3:951:13 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:952:3:952:12 | Mul | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:953:3:953:18 | Mul | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:953:7:953:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:954:3:954:15 | Mul | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:955:3:955:20 | Mul | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:955:21:955:21 | 128 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:956:3:956:27 | Constant | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:956:7:956:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:956:28:956:28 | 128 | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:957:3:957:36 | Mul | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:958:3:958:24 | Mul | ArgumentNode is missing PostUpdateNode. | +| membercallexpr.cpp:8:2:8:2 | c | ArgumentNode is missing PostUpdateNode. | +| membercallexpr_args.cpp:10:5:10:5 | d | ArgumentNode is missing PostUpdateNode. | +| membercallexpr_args.cpp:10:10:10:14 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| membercallexpr_args.cpp:10:17:10:21 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| misc.c:147:16:147:16 | i | ArgumentNode is missing PostUpdateNode. | +| misc.c:147:19:147:19 | j | ArgumentNode is missing PostUpdateNode. | +| misc.c:228:31:228:40 | global_int | ArgumentNode is missing PostUpdateNode. | +| misc.c:229:32:229:41 | global_int | ArgumentNode is missing PostUpdateNode. | +| misc.c:230:27:230:36 | global_int | ArgumentNode is missing PostUpdateNode. | +| misc.c:231:29:231:38 | global_int | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:13:21:13:35 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:14:21:14:21 | (const char *)... | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:28:18:28:23 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:28:26:28:28 | 256 | ArgumentNode is missing PostUpdateNode. | +| ms_assume.cpp:28:31:28:31 | s | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:11:7:11:10 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:11:12:11:14 | 101 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:28:7:28:10 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:28:12:28:14 | 101 | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:48:5:48:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| ms_try_mix.cpp:48:10:48:12 | 201 | ArgumentNode is missing PostUpdateNode. | +| newexpr.cpp:8:2:8:20 | Constant | ArgumentNode is missing PostUpdateNode. | +| newexpr.cpp:8:2:8:20 | new | ArgumentNode is missing PostUpdateNode. | +| newexpr.cpp:8:8:8:12 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| newexpr.cpp:8:15:8:19 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| no_dynamic_init.cpp:5:12:5:35 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:19:15:19:22 | Constant | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:20:18:20:30 | Constant | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:21:18:21:34 | Mul | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:26:31:26:53 | Constant | ArgumentNode is missing PostUpdateNode. | +| ops.cpp:26:31:26:53 | new | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:8:12:8:21 | (char *)... | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:8:24:8:24 | i | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:19:7:19:7 | 3 | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:21:7:21:7 | 4 | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:25:5:25:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| parameterinitializer.cpp:27:3:27:6 | my_c | ArgumentNode is missing PostUpdateNode. | +| pmcallexpr.cpp:8:11:8:11 | g | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:23:6:23:8 | obj | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:23:21:23:44 | call to getFunctionMemberPointer | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:23:46:23:50 | 0 | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:24:17:24:40 | call to getFunctionMemberPointer | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:24:42:24:45 | 1 | ArgumentNode is missing PostUpdateNode. | +| pointer_to_member.cpp:27:12:27:14 | obj | ArgumentNode is missing PostUpdateNode. | +| static_init_templates.cpp:20:12:20:12 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| static_init_templates.cpp:31:10:31:11 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| static_init_templates.cpp:236:7:236:7 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| static_init_templates.cpp:240:7:240:7 | FieldAddress | ArgumentNode is missing PostUpdateNode. | +| static_init_templates.cpp:249:21:249:23 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| static_init_templates.cpp:250:17:250:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| static_init_templates.cpp:251:20:251:23 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| staticlocals.cpp:29:14:29:14 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| staticmembercallexpr.cpp:8:2:8:2 | c | ArgumentNode is missing PostUpdateNode. | +| staticmembercallexpr_args.cpp:10:4:10:4 | d | ArgumentNode is missing PostUpdateNode. | +| staticmembercallexpr_args.cpp:10:9:10:13 | ... + ... | ArgumentNode is missing PostUpdateNode. | +| staticmembercallexpr_args.cpp:10:16:10:20 | ... - ... | ArgumentNode is missing PostUpdateNode. | +| stmt_expr.cpp:13:16:13:16 | VariableAddress | ArgumentNode is missing PostUpdateNode. | +| stmt_expr.cpp:13:18:13:18 | 1 | ArgumentNode is missing PostUpdateNode. | +| stream_it.cpp:19:13:19:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | +| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | +| try_catch.cpp:13:5:13:16 | VariableAddress | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.ql b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.ql new file mode 100644 index 00000000000..6d9f8e314f7 --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplConsistency::Consistency From d6b666cf8f8c9d9b6c78df7d443dfefedcbccdfa Mon Sep 17 00:00:00 2001 From: Alistair Christie Date: Wed, 11 Mar 2020 11:03:18 +0000 Subject: [PATCH 083/459] docs: Remove GitHub variable --- docs/language/learn-ql/csharp/introduce-libraries-csharp.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index b4f467a21bc..7bc8215b2f0 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1,7 +1,7 @@ CodeQL libraries for C# ======================= -When you're analyzing a C# program in {{ site.data.variables.product.prodname_dotcom }}, you can make use of the large collection of classes in the CodeQL libraries for C#. +When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL libraries for C#. About the CodeQL libraries for C# --------------------------------- @@ -1124,4 +1124,4 @@ Further reading - Visit :doc:`Tutorial: Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. \ No newline at end of file +- Learn more about the query console in `Using the query console `__. From 59691a1c6fd4884e626123becd4e6946cdfe729a Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 11 Mar 2020 15:33:54 +0000 Subject: [PATCH 084/459] Apply suggestions from code review Co-Authored-By: James Fletcher <42464962+jf205@users.noreply.github.com> Co-Authored-By: Felicity Chapman --- docs/language/learn-ql/beginner/crown-the-rightful-heir.rst | 2 +- docs/language/learn-ql/beginner/ql-tutorials.rst | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst index 6f740e2bf79..176a1b57155 100644 --- a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst +++ b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst @@ -1,7 +1,7 @@ Crown the rightful heir ======================= -This is QL detective puzzle that shows you how to use recursion in QL to write more complex queries. +This is a QL detective puzzle that shows you how to use recursion in QL to write more complex queries. King Basil's heir ----------------- diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index 5b7dab7177b..53f8ab7def2 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -1,14 +1,13 @@ QL tutorials ============ -Solve puzzles to learn the basics of QL before analyzing code with CodeQL. The tutorials teach you how to write queries and introduce you to key logic concepts along the way. +Solve puzzles to learn the basics of QL before you analyze code with CodeQL. The tutorials teach you how to write queries and introduce you to key logic concepts along the way. Before starting these tutorials, you can read the :doc:`Introduction to QL <../introduction-to-ql>` for a description of the language and some simple examples. .. toctree:: - :glob: find-the-thief catch-the-fire-starter crown-the-rightful-heir - cross-the-river \ No newline at end of file + cross-the-river From 92d82a9dd1e2a099666cdf29dbcab357d8facbd0 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 11 Mar 2020 15:44:39 +0000 Subject: [PATCH 085/459] Updates intros --- docs/language/learn-ql/beginner/catch-the-fire-starter.rst | 2 +- docs/language/learn-ql/beginner/cross-the-river.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst index 75e6370997d..95f2e86f974 100644 --- a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -1,7 +1,7 @@ Catch the fire starter ====================== -You can use QL predicates and classes to solve your second mystery as a QL detective. +Learn about QL predicates and classes to solve your second mystery as a QL detective. Just as you've successfully found the thief and returned the golden crown to the castle, another terrible crime is committed. Early in the morning, a few people start a fire in a field in the north of the village and destroy all the crops! diff --git a/docs/language/learn-ql/beginner/cross-the-river.rst b/docs/language/learn-ql/beginner/cross-the-river.rst index 3c48ce09667..7901ae00412 100644 --- a/docs/language/learn-ql/beginner/cross-the-river.rst +++ b/docs/language/learn-ql/beginner/cross-the-river.rst @@ -1,7 +1,7 @@ Cross the river =============== -You can use common QL features to write a query that finds a solution to the "River crossing" logic puzzle. +Use common QL features to write a query that finds a solution to the "River crossing" logic puzzle. Introduction ------------ From 02bec9f1e85e95fa9ad15fa591ee6668f9d90e23 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 11 Mar 2020 16:13:47 +0000 Subject: [PATCH 086/459] Update link text for remaining links to Python topics --- docs/language/learn-ql/intro-to-data-flow.rst | 2 +- docs/language/learn-ql/writing-queries/path-queries.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/intro-to-data-flow.rst b/docs/language/learn-ql/intro-to-data-flow.rst index f266849dfa7..4a879529d6f 100644 --- a/docs/language/learn-ql/intro-to-data-flow.rst +++ b/docs/language/learn-ql/intro-to-data-flow.rst @@ -17,7 +17,7 @@ See the following tutorials for more information about analyzing data flow in sp - :doc:`Analyzing data flow in C# ` - :doc:`Analyzing data flow in Java ` - :doc:`Analyzing data flow in JavaScript/TypeScript ` -- :doc:`Taint tracking and data flow analysis in Python ` +- :doc:`Analyzing data flow and tracking tainted data in Python ` .. pull-quote:: diff --git a/docs/language/learn-ql/writing-queries/path-queries.rst b/docs/language/learn-ql/writing-queries/path-queries.rst index 7b3d52515c3..2ab6dbe29b8 100644 --- a/docs/language/learn-ql/writing-queries/path-queries.rst +++ b/docs/language/learn-ql/writing-queries/path-queries.rst @@ -24,7 +24,7 @@ For more language-specific information on analyzing data flow, see: - :doc:`Analyzing data flow in C# <../csharp/dataflow>` - :doc:`Analyzing data flow in Java <../java/dataflow>` - :doc:`Analyzing data flow in JavaScript/TypeScript <../javascript/dataflow>` -- :doc:`Taint tracking and data flow analysis in Python <../python/taint-tracking>` +- :doc:`Analyzing data flow and tracking tainted data in Python <../python/taint-tracking>` Path query examples ******************* From 263e51f72e1b422a27d732a84c3ffb3534f33b31 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 12 Mar 2020 10:12:57 +0000 Subject: [PATCH 087/459] C++: Clean up the test. --- .../TaintedAllocationSize.expected | 3 ++- .../CWE-190/semmle/TaintedAllocationSize/test.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index f77bf73d52d..9b5811ebda5 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -6,4 +6,5 @@ | test.cpp:49:17:49:30 | new[] | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:52:21:52:27 | call to realloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:127:17:127:22 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:123:25:123:30 | call to getenv | user input (getenv) | +| test.cpp:127:17:127:22 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | +| test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp index 5cd5f0c0246..9998b751c53 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp @@ -39,10 +39,10 @@ int main(int argc, char **argv) { int tainted = atoi(argv[1]); MyStruct *arr1 = (MyStruct *)malloc(sizeof(MyStruct)); // GOOD - MyStruct *arr2 = (MyStruct *)malloc(tainted); // BAD + MyStruct *arr2 = (MyStruct *)malloc(tainted); // DUBIOUS (not multiplied by anything) MyStruct *arr3 = (MyStruct *)malloc(tainted * sizeof(MyStruct)); // BAD MyStruct *arr4 = (MyStruct *)malloc(getTainted() * sizeof(MyStruct)); // BAD [NOT DETECTED] - MyStruct *arr5 = (MyStruct *)malloc(sizeof(MyStruct) + tainted); // BAD [NOT DETECTED] + MyStruct *arr5 = (MyStruct *)malloc(sizeof(MyStruct) + tainted); // DUBIOUS (not multiplied by anything) int size = tainted * 8; char *chars1 = (char *)malloc(size); // BAD @@ -52,7 +52,7 @@ int main(int argc, char **argv) { arr1 = (MyStruct *)realloc(arr1, sizeof(MyStruct) * tainted); // BAD size = 8; - chars3 = new char[size]; // GOOD [FALSE POSITIVE] + chars3 = new char[size]; // GOOD return 0; } @@ -120,9 +120,9 @@ int bounded(int x, int limit) { } void open_file_bounded () { - int size = size = atoi(getenv("USER")); + int size = atoi(getenv("USER")); int bounded_size = bounded(size, MAX_SIZE); - int* a = (int*)malloc(bounded_size); // GOOD - int* b = (int*)malloc(size); // BAD -} \ No newline at end of file + int* a = (int*)malloc(bounded_size * sizeof(int)); // GOOD + int* b = (int*)malloc(size * sizeof(int)); // BAD +} From 26ed560bd7020ff0879bdee0f059b5e74ee12d7c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 12 Mar 2020 10:49:20 +0000 Subject: [PATCH 088/459] C++: Add new test cases. --- .../TaintedAllocationSize.expected | 6 ++ .../semmle/TaintedAllocationSize/test.cpp | 64 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 9b5811ebda5..8568cca660f 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -8,3 +8,9 @@ | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:127:17:127:22 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | +| test.cpp:134:3:134:8 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | +| test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | +| test.cpp:142:4:142:9 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | +| test.cpp:142:11:142:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | +| test.cpp:169:4:169:9 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:165:19:165:24 | call to getenv | user input (getenv) | +| test.cpp:169:11:169:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:165:19:165:24 | call to getenv | user input (getenv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp index 9998b751c53..317bbfc7c19 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp @@ -126,3 +126,67 @@ void open_file_bounded () { int* a = (int*)malloc(bounded_size * sizeof(int)); // GOOD int* b = (int*)malloc(size * sizeof(int)); // BAD } + +void more_bounded_tests() { + { + int size = atoi(getenv("USER")); + + malloc(size * sizeof(int)); // BAD + } + + { + int size = atoi(getenv("USER")); + + if (size > 0) + { + malloc(size * sizeof(int)); // BAD + } + } + + { + int size = atoi(getenv("USER")); + + if (size < 100) + { + malloc(size * sizeof(int)); // BAD [NOT DETECTED] + } + } + + { + int size = atoi(getenv("USER")); + + if ((size > 0) && (size < 100)) + { + malloc(size * sizeof(int)); // GOOD + } + } + + { + int size = atoi(getenv("USER")); + + if ((100 > size) && (0 < size)) + { + malloc(size * sizeof(int)); // GOOD [FALSE POSITIVE] + } + } + + { + int size = atoi(getenv("USER")); + + malloc(size * sizeof(int)); // BAD [NOT DETECTED] + + if ((size > 0) && (size < 100)) + { + // ... + } + } + + { + int size = atoi(getenv("USER")); + + if (size > 100) + { + malloc(size * sizeof(int)); // BAD [NOT DETECTED] + } + } +} From f4a1b410947460611ae7bbd0ab06c52cbfcfa280 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 12 Mar 2020 12:36:09 +0000 Subject: [PATCH 089/459] C++: Correct hasUpperBoundsCheck. --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 16 +++++++++++++--- .../code/cpp/security/TaintTrackingImpl.qll | 16 +++++++++++++--- .../TaintedAllocationSize.expected | 2 -- .../semmle/TaintedAllocationSize/test.cpp | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index e78d4d5d288..0a38b27ee4e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -130,7 +130,17 @@ private predicate writesVariable(StoreInstruction store, Variable var) { } /** - * A variable that has any kind of upper-bound check anywhere in the program + * A variable that has any kind of upper-bound check anywhere in the program. This is + * biased towards being inclusive because there are a lot of valid ways of doing an + * upper bounds checks if we don't consider where it occurs, for example: + * ``` + * if (x < 10) { sink(x); } + * + * if (10 > y) { sink(y); } + * + * if (z > 10) { z = 10; } + * sink(z); + * ``` */ // TODO: This coarse overapproximation, ported from the old taint tracking // library, could be replaced with an actual semantic check that a particular @@ -139,10 +149,10 @@ private predicate writesVariable(StoreInstruction store, Variable var) { // previously suppressed by this predicate by coincidence. private predicate hasUpperBoundsCheck(Variable var) { exists(RelationalOperation oper, VariableAccess access | - oper.getLeftOperand() = access and + oper.getAnOperand() = access and access.getTarget() = var and // Comparing to 0 is not an upper bound check - not oper.getRightOperand().getValue() = "0" + not oper.getAnOperand().getValue() = "0" ) } diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll index 3a37b43b319..c0d9ef6a912 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -328,14 +328,24 @@ GlobalOrNamespaceVariable globalVarFromId(string id) { } /** - * A variable that has any kind of upper-bound check anywhere in the program + * A variable that has any kind of upper-bound check anywhere in the program. This is + * biased towards being inclusive because there are a lot of valid ways of doing an + * upper bounds checks if we don't consider where it occurs, for example: + * ``` + * if (x < 10) { sink(x); } + * + * if (10 > y) { sink(y); } + * + * if (z > 10) { z = 10; } + * sink(z); + * ``` */ private predicate hasUpperBoundsCheck(Variable var) { exists(RelationalOperation oper, VariableAccess access | - oper.getLeftOperand() = access and + oper.getAnOperand() = access and access.getTarget() = var and // Comparing to 0 is not an upper bound check - not oper.getRightOperand().getValue() = "0" + not oper.getAnOperand().getValue() = "0" ) } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 8568cca660f..c48e2071525 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -12,5 +12,3 @@ | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | | test.cpp:142:4:142:9 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | | test.cpp:142:11:142:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | -| test.cpp:169:4:169:9 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:165:19:165:24 | call to getenv | user input (getenv) | -| test.cpp:169:11:169:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:165:19:165:24 | call to getenv | user input (getenv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp index 317bbfc7c19..4a1bbd8a9dc 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp @@ -166,7 +166,7 @@ void more_bounded_tests() { if ((100 > size) && (0 < size)) { - malloc(size * sizeof(int)); // GOOD [FALSE POSITIVE] + malloc(size * sizeof(int)); // GOOD } } From a0823a2582614bd2f9ab0c7e3514df523494adc1 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 12 Mar 2020 15:06:17 -0700 Subject: [PATCH 090/459] C++: add argv chi chain example to ssa test --- .../ir/ssa/aliased_ssa_ir.expected | 49 +++++++++++++++++++ .../ir/ssa/aliased_ssa_ir_unsound.expected | 49 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 8 +++ .../ir/ssa/unaliased_ssa_ir.expected | 44 +++++++++++++++++ .../ir/ssa/unaliased_ssa_ir_unsound.expected | 44 +++++++++++++++++ 5 files changed, 194 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index f44773f0fd3..62a45339b3d 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -1282,3 +1282,52 @@ ssa.cpp: # 268| v268_15(void) = UnmodeledUse : mu* # 268| v268_16(void) = AliasedUse : ~m270_11 # 268| v268_17(void) = ExitFunction : + +# 276| int main(int, char**) +# 276| Block 0 +# 276| v276_1(void) = EnterFunction : +# 276| m276_2(unknown) = AliasedDefinition : +# 276| m276_3(unknown) = InitializeNonLocal : +# 276| m276_4(unknown) = Chi : total:m276_2, partial:m276_3 +# 276| mu276_5(unknown) = UnmodeledDefinition : +# 276| r276_6(glval) = VariableAddress[argc] : +# 276| m276_7(int) = InitializeParameter[argc] : &:r276_6 +# 276| r276_8(glval) = VariableAddress[argv] : +# 276| m276_9(char **) = InitializeParameter[argv] : &:r276_8 +# 276| r276_10(char **) = Load : &:r276_8, m276_9 +# 276| m276_11(unknown) = InitializeIndirection[argv] : &:r276_10 +# 277| r277_1(glval) = FunctionAddress[unknownFunction] : +# 277| r277_2(glval) = VariableAddress[argc] : +# 277| r277_3(int) = Load : &:r277_2, m276_7 +# 277| r277_4(glval) = VariableAddress[argv] : +# 277| r277_5(char **) = Load : &:r277_4, m276_9 +# 277| v277_6(void) = Call : func:r277_1, 0:r277_3, 1:r277_5 +# 277| m277_7(unknown) = ^CallSideEffect : ~m276_11 +# 277| m277_8(unknown) = Chi : total:m276_11, partial:m277_7 +# 277| v277_9(void) = ^BufferReadSideEffect[1] : &:r277_5, ~m277_8 +# 277| m277_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r277_5 +# 277| m277_11(unknown) = Chi : total:m277_8, partial:m277_10 +# 278| r278_1(glval) = FunctionAddress[unknownFunction] : +# 278| r278_2(glval) = VariableAddress[argc] : +# 278| r278_3(int) = Load : &:r278_2, m276_7 +# 278| r278_4(glval) = VariableAddress[argv] : +# 278| r278_5(char **) = Load : &:r278_4, m276_9 +# 278| v278_6(void) = Call : func:r278_1, 0:r278_3, 1:r278_5 +# 278| m278_7(unknown) = ^CallSideEffect : ~m277_11 +# 278| m278_8(unknown) = Chi : total:m277_11, partial:m278_7 +# 278| v278_9(void) = ^BufferReadSideEffect[1] : &:r278_5, ~m278_8 +# 278| m278_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r278_5 +# 278| m278_11(unknown) = Chi : total:m278_8, partial:m278_10 +# 279| r279_1(glval) = VariableAddress[#return] : +# 279| r279_2(glval) = VariableAddress[argv] : +# 279| r279_3(char **) = Load : &:r279_2, m276_9 +# 279| r279_4(char *) = Load : &:r279_3, ~m278_11 +# 279| r279_5(char) = Load : &:r279_4, ~m278_11 +# 279| r279_6(int) = Convert : r279_5 +# 279| m279_7(int) = Store : &:r279_1, r279_6 +# 276| v276_12(void) = ReturnIndirection[argv] : &:r276_10, ~m278_11 +# 276| r276_13(glval) = VariableAddress[#return] : +# 276| v276_14(void) = ReturnValue : &:r276_13, m279_7 +# 276| v276_15(void) = UnmodeledUse : mu* +# 276| v276_16(void) = AliasedUse : ~m278_11 +# 276| v276_17(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index cb15cebf59c..dc765b62097 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1277,3 +1277,52 @@ ssa.cpp: # 268| v268_15(void) = UnmodeledUse : mu* # 268| v268_16(void) = AliasedUse : ~m269_7 # 268| v268_17(void) = ExitFunction : + +# 276| int main(int, char**) +# 276| Block 0 +# 276| v276_1(void) = EnterFunction : +# 276| m276_2(unknown) = AliasedDefinition : +# 276| m276_3(unknown) = InitializeNonLocal : +# 276| m276_4(unknown) = Chi : total:m276_2, partial:m276_3 +# 276| mu276_5(unknown) = UnmodeledDefinition : +# 276| r276_6(glval) = VariableAddress[argc] : +# 276| m276_7(int) = InitializeParameter[argc] : &:r276_6 +# 276| r276_8(glval) = VariableAddress[argv] : +# 276| m276_9(char **) = InitializeParameter[argv] : &:r276_8 +# 276| r276_10(char **) = Load : &:r276_8, m276_9 +# 276| m276_11(unknown) = InitializeIndirection[argv] : &:r276_10 +# 277| r277_1(glval) = FunctionAddress[unknownFunction] : +# 277| r277_2(glval) = VariableAddress[argc] : +# 277| r277_3(int) = Load : &:r277_2, m276_7 +# 277| r277_4(glval) = VariableAddress[argv] : +# 277| r277_5(char **) = Load : &:r277_4, m276_9 +# 277| v277_6(void) = Call : func:r277_1, 0:r277_3, 1:r277_5 +# 277| m277_7(unknown) = ^CallSideEffect : ~m276_4 +# 277| m277_8(unknown) = Chi : total:m276_4, partial:m277_7 +# 277| v277_9(void) = ^BufferReadSideEffect[1] : &:r277_5, ~m276_11 +# 277| m277_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r277_5 +# 277| m277_11(char *) = Chi : total:m276_11, partial:m277_10 +# 278| r278_1(glval) = FunctionAddress[unknownFunction] : +# 278| r278_2(glval) = VariableAddress[argc] : +# 278| r278_3(int) = Load : &:r278_2, m276_7 +# 278| r278_4(glval) = VariableAddress[argv] : +# 278| r278_5(char **) = Load : &:r278_4, m276_9 +# 278| v278_6(void) = Call : func:r278_1, 0:r278_3, 1:r278_5 +# 278| m278_7(unknown) = ^CallSideEffect : ~m277_8 +# 278| m278_8(unknown) = Chi : total:m277_8, partial:m278_7 +# 278| v278_9(void) = ^BufferReadSideEffect[1] : &:r278_5, ~m277_11 +# 278| m278_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r278_5 +# 278| m278_11(char *) = Chi : total:m277_11, partial:m278_10 +# 279| r279_1(glval) = VariableAddress[#return] : +# 279| r279_2(glval) = VariableAddress[argv] : +# 279| r279_3(char **) = Load : &:r279_2, m276_9 +# 279| r279_4(char *) = Load : &:r279_3, ~m278_11 +# 279| r279_5(char) = Load : &:r279_4, ~m278_8 +# 279| r279_6(int) = Convert : r279_5 +# 279| m279_7(int) = Store : &:r279_1, r279_6 +# 276| v276_12(void) = ReturnIndirection[argv] : &:r276_10, ~m278_11 +# 276| r276_13(glval) = VariableAddress[#return] : +# 276| v276_14(void) = ReturnValue : &:r276_13, m279_7 +# 276| v276_15(void) = UnmodeledUse : mu* +# 276| v276_16(void) = AliasedUse : ~m278_8 +# 276| v276_17(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index ee75a2f28e4..04f439636d9 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -269,4 +269,12 @@ void *MallocAliasing(void *s, int size) { void *buf = malloc(size); memcpy(buf, s, size); return buf; +} + +void unknownFunction(int argc, char **argv); + +int main(int argc, char **argv) { + unknownFunction(argc, argv); + unknownFunction(argc, argv); + return **argv; // Chi chain goes through side effects from unknownFunction } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index f08858d1a9c..da51da90a50 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -1188,3 +1188,47 @@ ssa.cpp: # 268| v268_14(void) = UnmodeledUse : mu* # 268| v268_15(void) = AliasedUse : ~mu268_4 # 268| v268_16(void) = ExitFunction : + +# 276| int main(int, char**) +# 276| Block 0 +# 276| v276_1(void) = EnterFunction : +# 276| mu276_2(unknown) = AliasedDefinition : +# 276| mu276_3(unknown) = InitializeNonLocal : +# 276| mu276_4(unknown) = UnmodeledDefinition : +# 276| r276_5(glval) = VariableAddress[argc] : +# 276| m276_6(int) = InitializeParameter[argc] : &:r276_5 +# 276| r276_7(glval) = VariableAddress[argv] : +# 276| m276_8(char **) = InitializeParameter[argv] : &:r276_7 +# 276| r276_9(char **) = Load : &:r276_7, m276_8 +# 276| mu276_10(unknown) = InitializeIndirection[argv] : &:r276_9 +# 277| r277_1(glval) = FunctionAddress[unknownFunction] : +# 277| r277_2(glval) = VariableAddress[argc] : +# 277| r277_3(int) = Load : &:r277_2, m276_6 +# 277| r277_4(glval) = VariableAddress[argv] : +# 277| r277_5(char **) = Load : &:r277_4, m276_8 +# 277| v277_6(void) = Call : func:r277_1, 0:r277_3, 1:r277_5 +# 277| mu277_7(unknown) = ^CallSideEffect : ~mu276_4 +# 277| v277_8(void) = ^BufferReadSideEffect[1] : &:r277_5, ~mu276_4 +# 277| mu277_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r277_5 +# 278| r278_1(glval) = FunctionAddress[unknownFunction] : +# 278| r278_2(glval) = VariableAddress[argc] : +# 278| r278_3(int) = Load : &:r278_2, m276_6 +# 278| r278_4(glval) = VariableAddress[argv] : +# 278| r278_5(char **) = Load : &:r278_4, m276_8 +# 278| v278_6(void) = Call : func:r278_1, 0:r278_3, 1:r278_5 +# 278| mu278_7(unknown) = ^CallSideEffect : ~mu276_4 +# 278| v278_8(void) = ^BufferReadSideEffect[1] : &:r278_5, ~mu276_4 +# 278| mu278_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r278_5 +# 279| r279_1(glval) = VariableAddress[#return] : +# 279| r279_2(glval) = VariableAddress[argv] : +# 279| r279_3(char **) = Load : &:r279_2, m276_8 +# 279| r279_4(char *) = Load : &:r279_3, ~mu276_4 +# 279| r279_5(char) = Load : &:r279_4, ~mu276_4 +# 279| r279_6(int) = Convert : r279_5 +# 279| m279_7(int) = Store : &:r279_1, r279_6 +# 276| v276_11(void) = ReturnIndirection[argv] : &:r276_9, ~mu276_4 +# 276| r276_12(glval) = VariableAddress[#return] : +# 276| v276_13(void) = ReturnValue : &:r276_12, m279_7 +# 276| v276_14(void) = UnmodeledUse : mu* +# 276| v276_15(void) = AliasedUse : ~mu276_4 +# 276| v276_16(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index f08858d1a9c..da51da90a50 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -1188,3 +1188,47 @@ ssa.cpp: # 268| v268_14(void) = UnmodeledUse : mu* # 268| v268_15(void) = AliasedUse : ~mu268_4 # 268| v268_16(void) = ExitFunction : + +# 276| int main(int, char**) +# 276| Block 0 +# 276| v276_1(void) = EnterFunction : +# 276| mu276_2(unknown) = AliasedDefinition : +# 276| mu276_3(unknown) = InitializeNonLocal : +# 276| mu276_4(unknown) = UnmodeledDefinition : +# 276| r276_5(glval) = VariableAddress[argc] : +# 276| m276_6(int) = InitializeParameter[argc] : &:r276_5 +# 276| r276_7(glval) = VariableAddress[argv] : +# 276| m276_8(char **) = InitializeParameter[argv] : &:r276_7 +# 276| r276_9(char **) = Load : &:r276_7, m276_8 +# 276| mu276_10(unknown) = InitializeIndirection[argv] : &:r276_9 +# 277| r277_1(glval) = FunctionAddress[unknownFunction] : +# 277| r277_2(glval) = VariableAddress[argc] : +# 277| r277_3(int) = Load : &:r277_2, m276_6 +# 277| r277_4(glval) = VariableAddress[argv] : +# 277| r277_5(char **) = Load : &:r277_4, m276_8 +# 277| v277_6(void) = Call : func:r277_1, 0:r277_3, 1:r277_5 +# 277| mu277_7(unknown) = ^CallSideEffect : ~mu276_4 +# 277| v277_8(void) = ^BufferReadSideEffect[1] : &:r277_5, ~mu276_4 +# 277| mu277_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r277_5 +# 278| r278_1(glval) = FunctionAddress[unknownFunction] : +# 278| r278_2(glval) = VariableAddress[argc] : +# 278| r278_3(int) = Load : &:r278_2, m276_6 +# 278| r278_4(glval) = VariableAddress[argv] : +# 278| r278_5(char **) = Load : &:r278_4, m276_8 +# 278| v278_6(void) = Call : func:r278_1, 0:r278_3, 1:r278_5 +# 278| mu278_7(unknown) = ^CallSideEffect : ~mu276_4 +# 278| v278_8(void) = ^BufferReadSideEffect[1] : &:r278_5, ~mu276_4 +# 278| mu278_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r278_5 +# 279| r279_1(glval) = VariableAddress[#return] : +# 279| r279_2(glval) = VariableAddress[argv] : +# 279| r279_3(char **) = Load : &:r279_2, m276_8 +# 279| r279_4(char *) = Load : &:r279_3, ~mu276_4 +# 279| r279_5(char) = Load : &:r279_4, ~mu276_4 +# 279| r279_6(int) = Convert : r279_5 +# 279| m279_7(int) = Store : &:r279_1, r279_6 +# 276| v276_11(void) = ReturnIndirection[argv] : &:r276_9, ~mu276_4 +# 276| r276_12(glval) = VariableAddress[#return] : +# 276| v276_13(void) = ReturnValue : &:r276_12, m279_7 +# 276| v276_14(void) = UnmodeledUse : mu* +# 276| v276_15(void) = AliasedUse : ~mu276_4 +# 276| v276_16(void) = ExitFunction : From cecbdae3e1d8e6066033c9ccca95b7ffd5fa61a5 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 13 Mar 2020 17:58:31 +0000 Subject: [PATCH 091/459] C++: Change note. --- change-notes/1.24/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.24/analysis-cpp.md b/change-notes/1.24/analysis-cpp.md index b4024b73307..c07d2004b74 100644 --- a/change-notes/1.24/analysis-cpp.md +++ b/change-notes/1.24/analysis-cpp.md @@ -22,6 +22,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. | No space for zero terminator (`cpp/no-space-for-terminator`) | More correct results | String arguments to formatting functions are now (usually) expected to be null terminated strings. | | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. | | No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. | +| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | Cases where the tainted allocation size is range checked are now more reliably excluded. | | Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. | | Unsafe array for days of the year (`cpp/leap-year/unsafe-array-for-days-of-the-year`) | | This query is no longer run on LGTM. | From 8055e91a5cf1f8e59dd9e3ba92a287da445405ee Mon Sep 17 00:00:00 2001 From: james Date: Wed, 11 Mar 2020 09:07:02 +0000 Subject: [PATCH 092/459] docs: update titles and intros (writing codeql queries) --- docs/language/learn-ql/intro-to-data-flow.rst | 7 ++++--- docs/language/learn-ql/locations.rst | 3 +++ .../writing-queries/debugging-queries.rst | 11 +++++++---- .../writing-queries/introduction-to-queries.rst | 16 +++++++++------- .../learn-ql/writing-queries/path-queries.rst | 6 ++++-- .../learn-ql/writing-queries/query-help.rst | 6 ++++-- .../learn-ql/writing-queries/query-metadata.rst | 9 +++++++-- .../writing-queries/select-statement.rst | 9 +++++++-- 8 files changed, 45 insertions(+), 22 deletions(-) diff --git a/docs/language/learn-ql/intro-to-data-flow.rst b/docs/language/learn-ql/intro-to-data-flow.rst index 4a879529d6f..dd30b7fbb96 100644 --- a/docs/language/learn-ql/intro-to-data-flow.rst +++ b/docs/language/learn-ql/intro-to-data-flow.rst @@ -1,10 +1,11 @@ -Introduction to data flow analysis with CodeQL -############################################## +About data flow analysis +######################## + +Data flow analysis is used to compute the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used. Overview ******** -Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used. Many CodeQL security queries implement data flow analysis, which can highlight the fate of potentially malicious or insecure data that can cause vulnerabilities in your code base. These queries help you understand if data is used in an insecure way, whether dangerous arguments are passed to functions, or whether sensitive data can leak. As well as highlighting potential security issues, you can also use data flow analysis to understand other aspects of how a program behaves, by finding, for example, uses of uninitialized variables and resource leaks. diff --git a/docs/language/learn-ql/locations.rst b/docs/language/learn-ql/locations.rst index df210819ef2..b2b5585a9d2 100644 --- a/docs/language/learn-ql/locations.rst +++ b/docs/language/learn-ql/locations.rst @@ -3,6 +3,9 @@ Locations and strings for QL entities .. Not sure how much of this topic needs to change, and what the title should be +CodeQL includes mechanisms for extracting the location of elements in a codebase. Use these mechanisms when writing custom CodeQL queries and libraries to help display information to users. + + Providing locations ------------------- diff --git a/docs/language/learn-ql/writing-queries/debugging-queries.rst b/docs/language/learn-ql/writing-queries/debugging-queries.rst index b0b03321354..3baac5e4bea 100644 --- a/docs/language/learn-ql/writing-queries/debugging-queries.rst +++ b/docs/language/learn-ql/writing-queries/debugging-queries.rst @@ -1,5 +1,10 @@ -Query writing: common performance issues -======================================== +Troubleshooting query performance +================================= + +Improve the performance of your CodeQL queries by following a few simple guidelines. + +About query performance +----------------------- This topic offers some simple tips on how to avoid common problems that can affect the performance of your queries. Before reading the tips below, it is worth reiterating a few important points about CodeQL and the QL language: @@ -19,9 +24,7 @@ Eliminate cartesian products The performance of a predicate can often be judged by considering roughly how many results it has. One way of creating badly performing predicates is by using two variables without relating them in any way, or only relating them using a negation. This leads to computing the `Cartesian product `__ between the sets of possible values for each variable, potentially generating a huge table of results. - This can occur if you don't specify restrictions on your variables. - For instance, consider the following predicate that checks whether a Java method ``m`` may access a field ``f``:: predicate mayAccess(Method m, Field f) { diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index abf8b942ecd..c29233f7f35 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -1,14 +1,17 @@ -Introduction to query files -########################### +About CodeQL queries +#################### + +CodeQL queries are used to analyze code for issues related to security, correctness, maintainability, and readability. Overview ******** -Queries are programs written with CodeQL. They are designed to highlight issues related to the security, correctness, maintainability, and readability of a code base. You can also write custom queries to find specific issues relevant to your own project. Three important types of query are: +CodeQL includes queries to find the relevant and interesting problems for a each supported language. You can also write custom queries to find specific issues relevant to your own project. + +The important types of query are: - **Alert queries**: queries that highlight issues in specific locations in your code. - **Path queries**: queries that describe the flow of information between a source and a sink in your code. -- **Metric queries**: queries that compute statistics for your code. You can add custom queries to `custom query packs `__ to analyze your projects in `LGTM `__, use them to analyze a database with the `CodeQL CLI `__, or you can contribute to the standard CodeQL queries in our `open source repository on GitHub `__. @@ -78,7 +81,7 @@ When writing your own alert queries, you would typically import the standard lib - C/C++: ``cpp`` - C#: ``csharp`` -- COBOL: ``cobol`` +- Go: ``go`` - Java: ``java`` - JavaScript/TypeScript: ``javascript`` - Python: ``python`` @@ -87,11 +90,10 @@ There are also libraries containing commonly used predicates, types, and other m You can explore the contents of all the standard libraries in the `CodeQL library reference documentation `__ or in the `GitHub repository `__. - Optional CodeQL classes and predicates -------------------------------------- -You can customize your analysis by defining your own predicates and classes in the query. See `Defining a predicate `__ and `Defining a class `__ for further details. +You can customize your analysis by defining your own predicates and classes in the query. For further information, see `Defining a predicate `__ and `Defining a class `__. From clause =========== diff --git a/docs/language/learn-ql/writing-queries/path-queries.rst b/docs/language/learn-ql/writing-queries/path-queries.rst index 2ab6dbe29b8..6392797c90c 100644 --- a/docs/language/learn-ql/writing-queries/path-queries.rst +++ b/docs/language/learn-ql/writing-queries/path-queries.rst @@ -1,5 +1,7 @@ -Constructing path queries -######################### +Creating path queries +##################### + +You can create path queries to visualize the flow of information through a codebase. Overview ======== diff --git a/docs/language/learn-ql/writing-queries/query-help.rst b/docs/language/learn-ql/writing-queries/query-help.rst index c3692b7fac0..0ab52f845a8 100644 --- a/docs/language/learn-ql/writing-queries/query-help.rst +++ b/docs/language/learn-ql/writing-queries/query-help.rst @@ -1,5 +1,7 @@ -Query help reference -******************** +Query help files +**************** + +Query help files tell users the purpose of a query, and recommend how to solve the potential problem the query finds. This topic provides detailed information on the structure of query help files. For more information about how to write useful query help in a style that is consistent with the standard CodeQL queries, see the `Query help style guide `__ on GitHub. diff --git a/docs/language/learn-ql/writing-queries/query-metadata.rst b/docs/language/learn-ql/writing-queries/query-metadata.rst index 51af3018fdd..8beb9f7cab1 100644 --- a/docs/language/learn-ql/writing-queries/query-metadata.rst +++ b/docs/language/learn-ql/writing-queries/query-metadata.rst @@ -1,5 +1,10 @@ -Query metadata -============== +Metadata for CodeQL queries +=========================== + +Metadata is used to tell users important information about CodeQL queries. You must include the correct query metadata in a query to be able to view query results in source code. + +About query metadata +-------------------- Any query that is run as part of an analysis includes a number of properties, known as query metadata. Metadata is included at the top of each query file as the content of a `QLDoc `__ comment. For alerts and path queries, this metadata tells LGTM and the CodeQL `extension for VS Code `__ how to handle the query and display its results correctly. diff --git a/docs/language/learn-ql/writing-queries/select-statement.rst b/docs/language/learn-ql/writing-queries/select-statement.rst index c974f8a21d6..d754f841eac 100644 --- a/docs/language/learn-ql/writing-queries/select-statement.rst +++ b/docs/language/learn-ql/writing-queries/select-statement.rst @@ -1,5 +1,10 @@ -Defining 'select' statements -============================ +Defining the results of a query +=============================== + +You can control how analysis results are displayed in source code by modifying a query's ``select`` statement. + +About query results +------------------- The information contained in the results of a query is controlled by the ``select`` statement. Part of the process of developing a useful query is to make the results clear and easy for other users to understand. When you write your own queries in the query console or in the CodeQL `extension for VS Code `__ there are no constraints on what can be selected. From 6721495160dbfba5086f1da58d393318c7f84e99 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 16 Mar 2020 11:46:54 +0000 Subject: [PATCH 093/459] docs: retitle locations --- docs/language/learn-ql/locations.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/locations.rst b/docs/language/learn-ql/locations.rst index b2b5585a9d2..a06f428bef8 100644 --- a/docs/language/learn-ql/locations.rst +++ b/docs/language/learn-ql/locations.rst @@ -1,4 +1,4 @@ -Locations and strings for QL entities +Providing locations in CodeQL queries ===================================== .. Not sure how much of this topic needs to change, and what the title should be @@ -6,8 +6,8 @@ Locations and strings for QL entities CodeQL includes mechanisms for extracting the location of elements in a codebase. Use these mechanisms when writing custom CodeQL queries and libraries to help display information to users. -Providing locations -------------------- +About locations +--------------- When displaying information to the user, LGTM needs to be able to extract location information from the results of a query. In order to do this, all QL classes which can provide location information should do this by using one of the following mechanisms: From ff07f3d3b77e1f9c8706ab5c8388fd8c0a17bafc Mon Sep 17 00:00:00 2001 From: james Date: Thu, 12 Mar 2020 12:32:09 +0000 Subject: [PATCH 094/459] docs: 'About CodeQL queries' content updates --- .../introduction-to-queries.rst | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index c29233f7f35..27cc524249b 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -6,12 +6,11 @@ CodeQL queries are used to analyze code for issues related to security, correctn Overview ******** -CodeQL includes queries to find the relevant and interesting problems for a each supported language. You can also write custom queries to find specific issues relevant to your own project. - -The important types of query are: +CodeQL includes queries to find the most relevant and interesting problems for each supported language. You can also write custom queries to find specific issues relevant to your own project. The important types of query are: - **Alert queries**: queries that highlight issues in specific locations in your code. - **Path queries**: queries that describe the flow of information between a source and a sink in your code. +- **Metric queries**: queries that compute statistics for your code. You can add custom queries to `custom query packs `__ to analyze your projects in `LGTM `__, use them to analyze a database with the `CodeQL CLI `__, or you can contribute to the standard CodeQL queries in our `open source repository on GitHub `__. @@ -24,10 +23,9 @@ You can add custom queries to `custom query packs `__ and in the `Results view `__ in VS Code. -This topic is a basic introduction to structuring query files. You can find further information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language handbook `__ and the `QL language specification `__. +This topic is a basic introduction to query files. You can find further information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language handbook `__ and the `QL language specification `__. For information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide `__. - Basic query structure ********************* @@ -130,6 +128,24 @@ Select clauses for metric queries (``@kind metric``) consist of two 'columns', w - ``element``: a code element that is identified by the query, which defines where the alert is displayed. - ``metric``: the result of the metric that the query computes. +Viewing the standard CodeQL queries +*********************************** + +One of the easiest ways to get started writing your own queries is to modify an existing query. To see view the standard CodeQL queries, or to try out other examples, visit the `CodeQL `__ and `CodeQL for Go `__ repositories on GitHub. + +You can also find examples of queries developed to find security vulnerabilities and bugs in open-source software projects on the `GitHub Security Lab website `__ and in the associated `repository `__. + +Contributing queries +******************** + +Contributions to the standard queries and libraries are very welcome---see our `contributing guidelines `__ for further information. +If you are contributing a query to the open source GitHub repository, writing a custom query for LGTM, or using a custom query in an analysis with the CodeQL CLI, then you need to include extra metadata in your query to ensure that the query results are interpreted and displayed correctly. See the following topics for more information on query metadata: + +- :doc:`Query metadata reference ` +- `Query metadata style guide on GitHub `__ + +Query contributions to the open source GitHub repository may also have an accompanying query help file to provide information about their purpose for other users. For more information on writing query help, see the `Query help style guide on GitHub `__ and the :doc:`Query help reference `. + Query help files **************** From 764303acb52b017d138e94d4c597438ac5dc0f0f Mon Sep 17 00:00:00 2001 From: james Date: Thu, 12 Mar 2020 20:58:41 +0000 Subject: [PATCH 095/459] docs: rework 'CodeQL queries' landing page --- .../writing-queries/writing-queries.rst | 59 +++---------------- 1 file changed, 9 insertions(+), 50 deletions(-) diff --git a/docs/language/learn-ql/writing-queries/writing-queries.rst b/docs/language/learn-ql/writing-queries/writing-queries.rst index e08048953c0..44f55726588 100644 --- a/docs/language/learn-ql/writing-queries/writing-queries.rst +++ b/docs/language/learn-ql/writing-queries/writing-queries.rst @@ -1,57 +1,16 @@ -Writing CodeQL queries -###################### +CodeQL queries +############## -If you are familiar with CodeQL, you can modify the existing queries or write custom queries to analyze, improve, and secure your own projects. Get started by reading the information for query writers and viewing the examples provided below. - -Information for query writers -***************************** +CodeQL queries are used in code scanning analyses to find problems in source code, including potential security vulnerabilities. .. toctree:: - :glob: - :hidden: + :maxdepth: 1 introduction-to-queries - path-queries - ../intro-to-data-flow - select-statement - ../locations - debugging-queries - - -Visit `Learning CodeQL `__ to find basic information about CodeQL. This includes information about the underlying query language QL, as well as help and advice on writing queries for specific programming languages. -To learn more about the structure of query files, the key information to include when writing your own queries, and how to format them for clarity and consistency, see the following topics: - -- :doc:`Introduction to query files `–an introduction to the information contained in a basic query file. -- :doc:`Constructing path queries `–a quick guide to structuring path queries to use in security research. -- :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`–a brief introduction to modeling data flow using CodeQL. -- :doc:`Defining 'select' statements `–further detail on developing query alert messages to provide extra information in your query results. -- :doc:`Locations and strings for CodeQL entities <../locations>`–further detail on providing location information in query results. -- `CodeQL style guide on GitHub `__–a guide to formatting your queries for consistency and clarity. - -Viewing existing CodeQL queries -******************************* - -The easiest way to get started writing your own queries is to modify an existing query. To see these queries, or to try out the CodeQL query cookbooks, visit `Exploring CodeQL queries `__. -You can also find all the CodeQL queries in our `open source repository on GitHub `__. - -You can also find examples of queries developed to find security vulnerabilities and bugs in open-source software projects on the `GitHub Security Lab website `__ and in the associated `repository `__. - -Contributing queries -******************** - -.. toctree:: - :glob: - :hidden: - query-metadata query-help - -Contributions to the standard queries and libraries are very welcome–see our `contributing guidelines `__ for further information. -If you are contributing a query to the open source GitHub repository, writing a custom query for LGTM, or using a custom query in an analysis with our command-line tools, then you need to include extra metadata in your query to ensure that the query results are interpreted and displayed correctly. See the following topics for more information on query metadata: - -.. TODO: Change "command-line tools" to a link to the CodeQL CLI? - -- :doc:`Query metadata reference ` -- `Query metadata style guide on GitHub `__ - -Query contributions to the open source GitHub repository may also have an accompanying query help file to provide information about their purpose for other users. For more information on writing query help, see the `Query help style guide on GitHub `__ and the :doc:`Query help reference `. \ No newline at end of file + select-statement + ../locations + ../intro-to-data-flow + path-queries + debugging-queries \ No newline at end of file From b7f87225d9f64aba4716cbdee4553d645f1d4c2e Mon Sep 17 00:00:00 2001 From: james Date: Fri, 13 Mar 2020 17:01:40 +0000 Subject: [PATCH 096/459] docs: update links following titles changes --- docs/language/learn-ql/cpp/dataflow.rst | 2 +- docs/language/learn-ql/csharp/dataflow.rst | 2 +- docs/language/learn-ql/intro-to-data-flow.rst | 2 +- docs/language/learn-ql/java/dataflow.rst | 2 +- .../learn-ql/javascript/dataflow-cheat-sheet.rst | 2 +- docs/language/learn-ql/javascript/dataflow.rst | 2 +- .../writing-queries/introduction-to-queries.rst | 16 ++++++++-------- .../learn-ql/writing-queries/path-queries.rst | 4 ++-- .../learn-ql/writing-queries/query-metadata.rst | 4 ++-- .../writing-queries/select-statement.rst | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index a620e8664bc..c3ba52cd62f 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -6,7 +6,7 @@ You can use data-flow analysis to track the flow of potentially malicious or ins About data flow --------------- -Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For more background information, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Local data flow --------------- diff --git a/docs/language/learn-ql/csharp/dataflow.rst b/docs/language/learn-ql/csharp/dataflow.rst index 22e939caf37..e86b07c1edf 100644 --- a/docs/language/learn-ql/csharp/dataflow.rst +++ b/docs/language/learn-ql/csharp/dataflow.rst @@ -9,7 +9,7 @@ About this article This article describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries. The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Local data flow --------------- diff --git a/docs/language/learn-ql/intro-to-data-flow.rst b/docs/language/learn-ql/intro-to-data-flow.rst index dd30b7fbb96..e509d3a8c16 100644 --- a/docs/language/learn-ql/intro-to-data-flow.rst +++ b/docs/language/learn-ql/intro-to-data-flow.rst @@ -24,7 +24,7 @@ See the following tutorials for more information about analyzing data flow in sp Note - Data flow analysis is used extensively in path queries. To learn more about path queries, see :doc:`Constructing path queries `. + Data flow analysis is used extensively in path queries. To learn more about path queries, see :doc:`Creating path queries `. .. _data-flow-graph: diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index 51f186bbb22..19fcbf081a5 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -9,7 +9,7 @@ About this article This article describes how data flow analysis is implemented in the CodeQL libraries for Java and includes examples to help you write your own data flow queries. The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Local data flow --------------- diff --git a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst index b87c1062317..a78dc116e37 100644 --- a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst +++ b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst @@ -34,7 +34,7 @@ This query reports flow paths which: - Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep `__. - End at a node matched by `isSink `__. -See also: `Global data flow `__ and :doc:`Constructing path queries <../writing-queries/path-queries>`. +See also: `Global data flow `__ and :doc:`Creating path queries <../writing-queries/path-queries>`. DataFlow module --------------- diff --git a/docs/language/learn-ql/javascript/dataflow.rst b/docs/language/learn-ql/javascript/dataflow.rst index f1ede8c3074..10903cfbd91 100644 --- a/docs/language/learn-ql/javascript/dataflow.rst +++ b/docs/language/learn-ql/javascript/dataflow.rst @@ -9,7 +9,7 @@ The various sections in this article describe how to utilize the libraries for l As our running example, we will develop a query that identifies command-line arguments that are passed as a file path to the standard Node.js ``readFile`` function. While this is not a problematic pattern as such, it is typical of the kind of reasoning that is frequently used in security queries. -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Data flow nodes --------------- diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index 27cc524249b..c9f74273f78 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -45,7 +45,7 @@ Basic query structure where /* ... logical formula ... */ select /* ... expressions ... */ -The following sections describe the information that is typically included in a query file for alerts and metrics. Path queries are discussed in more detail in :doc:`Constructing path queries `. +The following sections describe the information that is typically included in a query file for alerts and metrics. Path queries are discussed in more detail in :doc:`Creating path queries `. Query metadata ============== @@ -84,7 +84,7 @@ When writing your own alert queries, you would typically import the standard lib - JavaScript/TypeScript: ``javascript`` - Python: ``python`` -There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. See :doc:`Constructing path queries ` for further information. +There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. See :doc:`Creating path queries ` for further information. You can explore the contents of all the standard libraries in the `CodeQL library reference documentation `__ or in the `GitHub repository `__. @@ -117,9 +117,9 @@ Select clauses for alert queries (``@kind problem``) consist of two 'columns', w - ``element``: a code element that is identified by the query, which defines where the alert is displayed. - ``string``: a message, which can also include links and placeholders, explaining why the alert was generated. -The alert message defined in the final column of the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining 'select' statements `. +The alert message defined in the final column of the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining the results of a query `. -Select clauses for path queries (``@kind path-problem``) are crafted to display both an alert and the source and sink of an associated path graph. See :doc:`Constructing path queries ` for further information. +Select clauses for path queries (``@kind path-problem``) are crafted to display both an alert and the source and sink of an associated path graph. See :doc:`Creating path queries ` for further information. Select clauses for metric queries (``@kind metric``) consist of two 'columns', with the following structure:: @@ -141,21 +141,21 @@ Contributing queries Contributions to the standard queries and libraries are very welcome---see our `contributing guidelines `__ for further information. If you are contributing a query to the open source GitHub repository, writing a custom query for LGTM, or using a custom query in an analysis with the CodeQL CLI, then you need to include extra metadata in your query to ensure that the query results are interpreted and displayed correctly. See the following topics for more information on query metadata: -- :doc:`Query metadata reference ` +- :doc:`Metadata for CodeQL queries ` - `Query metadata style guide on GitHub `__ -Query contributions to the open source GitHub repository may also have an accompanying query help file to provide information about their purpose for other users. For more information on writing query help, see the `Query help style guide on GitHub `__ and the :doc:`Query help reference `. +Query contributions to the open source GitHub repository may also have an accompanying query help file to provide information about their purpose for other users. For more information on writing query help, see the `Query help style guide on GitHub `__ and the :doc:`Query help files `. Query help files **************** -When you write a custom query, we also recommend that you write a query help file to explain the purpose of the query to other users. For more information, see the `Query help style guide `__ on GitHub, and the :doc:`Query help reference `. +When you write a custom query, we also recommend that you write a query help file to explain the purpose of the query to other users. For more information, see the `Query help style guide `__ on GitHub, and the :doc:`Query help files `. What next? ========== - See the queries used in real-life variant analysis on the `GitHub Security Lab website `__. -- To learn more about writing path queries, see :doc:`Constructing path queries `. +- To learn more about writing path queries, see :doc:`Creating path queries `. - Take a look at the `built-in queries `__ to see examples of the queries included in CodeQL. - Explore the `query cookbooks `__ to see how to access the basic language elements contained in the CodeQL libraries. - For a full list of resources to help you learn CodeQL, including beginner tutorials and language-specific examples, visit `Learning CodeQL `__. \ No newline at end of file diff --git a/docs/language/learn-ql/writing-queries/path-queries.rst b/docs/language/learn-ql/writing-queries/path-queries.rst index 6392797c90c..0d2262a593a 100644 --- a/docs/language/learn-ql/writing-queries/path-queries.rst +++ b/docs/language/learn-ql/writing-queries/path-queries.rst @@ -97,7 +97,7 @@ Path query metadata ******************* Path query metadata must contain the property ``@kind path-problem``–this ensures that query results are interpreted and displayed correctly. -The other metadata requirements depend on how you intend to run the query. See the section on query metadata in :doc:`Introduction to query files ` for further information. +The other metadata requirements depend on how you intend to run the query. See the section on query metadata in :doc:`About CodeQL queries ` for further information. Generating path explanations **************************** @@ -187,7 +187,7 @@ Each result generated by your query is displayed at a single location in the sam The ``element`` that you select in the first column depends on the purpose of the query and the type of issue that it is designed to find. This is particularly important for security issues. For example, if you believe the ``source`` value to be globally invalid or malicious it may be best to display the alert at the ``source``. In contrast, you should consider displaying the alert at the ``sink`` if you believe it is the element that requires sanitization. -The alert message defined in the final column in the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining 'select' statements `. +The alert message defined in the final column in the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining the results of a query `. What next? ********** diff --git a/docs/language/learn-ql/writing-queries/query-metadata.rst b/docs/language/learn-ql/writing-queries/query-metadata.rst index 8beb9f7cab1..28c3754ca85 100644 --- a/docs/language/learn-ql/writing-queries/query-metadata.rst +++ b/docs/language/learn-ql/writing-queries/query-metadata.rst @@ -15,7 +15,7 @@ You can also add metric queries to LGTM, but the results are not shown. To see t Note - The exact metadata requirement depends on how you are going to run your query. For more information, see the section on query metadata in :doc:`Introduction to query files `. + The exact metadata requirement depends on how you are going to run your query. For more information, see the section on query metadata in :doc:`About CodeQL queries `. Core properties --------------- @@ -29,7 +29,7 @@ The following properties are supported by all query files: +-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``@id`` | ```` | A sequence of words composed of lowercase letters or digits, delimited by ``/`` or ``-``, identifying and classifying the query. Each query must have a **unique** ID. To ensure this, it may be helpful to use a fixed structure for each ID. For example, the standard LGTM queries have the following format: ``/``. | +-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@kind`` | | ``problem`` | Identifies the query is an alert (``@kind problem``), a path (``@kind path-problem``), or a metric (``@kind metric``). For further information on these query types, see :doc:`Introduction to query files ` | +| ``@kind`` | | ``problem`` | Identifies the query is an alert (``@kind problem``), a path (``@kind path-problem``), or a metric (``@kind metric``). For further information on these query types, see :doc:`About CodeQL queries ` | | | | ``path-problem`` | | | | | ``metric`` | | +-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/docs/language/learn-ql/writing-queries/select-statement.rst b/docs/language/learn-ql/writing-queries/select-statement.rst index d754f841eac..5531a958e3e 100644 --- a/docs/language/learn-ql/writing-queries/select-statement.rst +++ b/docs/language/learn-ql/writing-queries/select-statement.rst @@ -27,7 +27,7 @@ If you look at some of the LGTM queries, you'll see that they can select extra e Note - An in-depth discussion of ``select`` statements for path and metric queries is not included in this topic. However, you can develop the string column of the ``select`` statement in the same way as for alert queries. For more specific information about path queries, see :doc:`Constructing path queries `. + An in-depth discussion of ``select`` statements for path and metric queries is not included in this topic. However, you can develop the string column of the ``select`` statement in the same way as for alert queries. For more specific information about path queries, see :doc:`Creating path queries `. Developing a select statement ----------------------------- From 42b6c116aaca0fb97231c22fd0c6d98042012f50 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 16 Mar 2020 09:36:15 +0000 Subject: [PATCH 097/459] docs: open-source -> open source --- docs/language/learn-ql/ql-training.rst | 2 +- .../learn-ql/writing-queries/introduction-to-queries.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index fcb14476d88..d56833ddae9 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -62,4 +62,4 @@ More resources - If you are completely new to CodeQL, look at our introductory topics in :doc:`Learning CodeQL `. - To find more detailed information about how to write queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. -- To see examples of CodeQL queries that have been used to find security vulnerabilities and bugs in open-source software projects, visit the `GitHub Security Lab website `__ and the associated `repository `__. \ No newline at end of file +- To see examples of CodeQL queries that have been used to find security vulnerabilities and bugs in open source software projects, visit the `GitHub Security Lab website `__ and the associated `repository `__. \ No newline at end of file diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index c9f74273f78..eaf33505121 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -131,9 +131,9 @@ Select clauses for metric queries (``@kind metric``) consist of two 'columns', w Viewing the standard CodeQL queries *********************************** -One of the easiest ways to get started writing your own queries is to modify an existing query. To see view the standard CodeQL queries, or to try out other examples, visit the `CodeQL `__ and `CodeQL for Go `__ repositories on GitHub. +One of the easiest ways to get started writing your own queries is to modify an existing query. To view the standard CodeQL queries, or to try out other examples, visit the `CodeQL `__ and `CodeQL for Go `__ repositories on GitHub. -You can also find examples of queries developed to find security vulnerabilities and bugs in open-source software projects on the `GitHub Security Lab website `__ and in the associated `repository `__. +You can also find examples of queries developed to find security vulnerabilities and bugs in open source software projects on the `GitHub Security Lab website `__ and in the associated `repository `__. Contributing queries ******************** From d35d440624e08512b95c9faafce47b3d7c4b3230 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 16 Mar 2020 18:48:08 +0000 Subject: [PATCH 098/459] docs: address review comments --- .../writing-queries/introduction-to-queries.rst | 14 +++++++------- .../learn-ql/writing-queries/path-queries.rst | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index eaf33505121..e10793c06bc 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -23,8 +23,8 @@ You can add custom queries to `custom query packs `__ and in the `Results view `__ in VS Code. -This topic is a basic introduction to query files. You can find further information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language handbook `__ and the `QL language specification `__. -For information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide `__. +This topic is a basic introduction to query files. You can find more information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language handbook `__ and the `QL language specification `__. +For more information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide `__. Basic query structure ********************* @@ -55,7 +55,7 @@ Query metadata is used to identify your custom queries when they are added to th - If you are contributing a query to the GitHub repository, please read the `query metadata style guide `__. - If you are adding a custom query to a query pack for analysis using LGTM , see `Writing custom queries to include in LGTM analysis `__. - If you are analyzing a database using the `CodeQL CLI `__, your query metadata must contain ``@kind``. -- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. See `Using the query console `__ and `Using the extension `__ for further information. +- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. For more information, `Using the query console `__ and `Using the extension `__. .. pull-quote:: @@ -84,7 +84,7 @@ When writing your own alert queries, you would typically import the standard lib - JavaScript/TypeScript: ``javascript`` - Python: ``python`` -There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. See :doc:`Creating path queries ` for further information. +There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. For more information, see :doc:`Creating path queries `. You can explore the contents of all the standard libraries in the `CodeQL library reference documentation `__ or in the `GitHub repository `__. @@ -117,9 +117,9 @@ Select clauses for alert queries (``@kind problem``) consist of two 'columns', w - ``element``: a code element that is identified by the query, which defines where the alert is displayed. - ``string``: a message, which can also include links and placeholders, explaining why the alert was generated. -The alert message defined in the final column of the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining the results of a query `. +You can modify the alert message defined in the final column of the ``select`` statement to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining the results of a query `. -Select clauses for path queries (``@kind path-problem``) are crafted to display both an alert and the source and sink of an associated path graph. See :doc:`Creating path queries ` for further information. +Select clauses for path queries (``@kind path-problem``) are crafted to display both an alert and the source and sink of an associated path graph. For more information, see :doc:`Creating path queries `. Select clauses for metric queries (``@kind metric``) consist of two 'columns', with the following structure:: @@ -138,7 +138,7 @@ You can also find examples of queries developed to find security vulnerabilities Contributing queries ******************** -Contributions to the standard queries and libraries are very welcome---see our `contributing guidelines `__ for further information. +Contributions to the standard queries and libraries are very welcome. For more information, see our `contributing guidelines `__. If you are contributing a query to the open source GitHub repository, writing a custom query for LGTM, or using a custom query in an analysis with the CodeQL CLI, then you need to include extra metadata in your query to ensure that the query results are interpreted and displayed correctly. See the following topics for more information on query metadata: - :doc:`Metadata for CodeQL queries ` diff --git a/docs/language/learn-ql/writing-queries/path-queries.rst b/docs/language/learn-ql/writing-queries/path-queries.rst index 0d2262a593a..41e9d0742eb 100644 --- a/docs/language/learn-ql/writing-queries/path-queries.rst +++ b/docs/language/learn-ql/writing-queries/path-queries.rst @@ -97,7 +97,7 @@ Path query metadata ******************* Path query metadata must contain the property ``@kind path-problem``–this ensures that query results are interpreted and displayed correctly. -The other metadata requirements depend on how you intend to run the query. See the section on query metadata in :doc:`About CodeQL queries ` for further information. +The other metadata requirements depend on how you intend to run the query. For more information, see `Query metadata `__. Generating path explanations **************************** @@ -187,7 +187,7 @@ Each result generated by your query is displayed at a single location in the sam The ``element`` that you select in the first column depends on the purpose of the query and the type of issue that it is designed to find. This is particularly important for security issues. For example, if you believe the ``source`` value to be globally invalid or malicious it may be best to display the alert at the ``source``. In contrast, you should consider displaying the alert at the ``sink`` if you believe it is the element that requires sanitization. -The alert message defined in the final column in the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining the results of a query `. +The alert message defined in the final column in the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For more information, see :doc:`Defining the results of a query `. What next? ********** From d615c5806092aaff2fa5c6d5aa4b51c13a403b66 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 17 Mar 2020 09:06:32 +0000 Subject: [PATCH 099/459] docs: tidy up a few links --- .../csharp/introduce-libraries-csharp.rst | 2 +- docs/language/learn-ql/csharp/ql-for-csharp.rst | 2 +- docs/language/learn-ql/java/ql-for-java.rst | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index 7bc8215b2f0..501c8591f2d 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1122,6 +1122,6 @@ Here is the fixed version: Further reading --------------- -- Visit :doc:`Tutorial: Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. +- Visit :doc:`Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/csharp/ql-for-csharp.rst b/docs/language/learn-ql/csharp/ql-for-csharp.rst index 67bec1ff60b..02dddda60ec 100644 --- a/docs/language/learn-ql/csharp/ql-for-csharp.rst +++ b/docs/language/learn-ql/csharp/ql-for-csharp.rst @@ -20,7 +20,7 @@ These topics provide an overview of the CodeQL libraries for C# and show example -- :doc:`Tutorial: Analyzing data flow in C# ` demonstrates how to write queries using the standard data flow and taint tracking libraries for C#. +- :doc:`Analyzing data flow in C# ` demonstrates how to write queries using the standard data flow and taint tracking libraries for C#. Other resources diff --git a/docs/language/learn-ql/java/ql-for-java.rst b/docs/language/learn-ql/java/ql-for-java.rst index 606eef327cd..9ff0b24438a 100644 --- a/docs/language/learn-ql/java/ql-for-java.rst +++ b/docs/language/learn-ql/java/ql-for-java.rst @@ -21,21 +21,21 @@ These topics provide an overview of the CodeQL libraries for Java and show examp - `Basic Java query `__ describes how to write and run queries using LGTM. -- :doc:`Introducing the CodeQL libraries for Java ` introduces the standard libraries used to write queries for Java code. +- :doc:`CodeQL libraries for Java ` introduces the standard libraries used to write queries for Java code. -- :doc:`Tutorial: Analyzing data flow in Java ` demonstrates how to write queries using the standard data flow and taint tracking libraries for Java. +- :doc:`Analyzing data flow in Java ` demonstrates how to write queries using the standard data flow and taint tracking libraries for Java. -- :doc:`Tutorial: Types and the class hierarchy ` introduces the classes for representing a program's class hierarchy by means of examples. +- :doc:`Types in Java ` introduces the classes for representing a program's class hierarchy by means of examples. -- :doc:`Tutorial: Expressions and statements ` introduces the classes for representing a program's syntactic structure by means of examples. +- :doc:`Expressions and statements in Java ` introduces the classes for representing a program's syntactic structure by means of examples. -- :doc:`Tutorial: Navigating the call graph ` is a worked example of how to write a query that navigates a program's call graph to find unused methods. +- :doc:`Navigating the call graph ` is a worked example of how to write a query that navigates a program's call graph to find unused methods. -- :doc:`Tutorial: Annotations ` introduces the classes for representing annotations by means of examples. +- :doc:`Annotations in Java ` introduces the classes for representing annotations by means of examples. -- :doc:`Tutorial: Javadoc ` introduces the classes for representing Javadoc comments by means of examples. +- :doc:`Javadoc ` introduces the classes for representing Javadoc comments by means of examples. -- :doc:`Tutorial: Working with source locations ` is a worked example of how to write a query that uses the location information provided in the database for finding likely bugs. +- :doc:`Working with source locations ` is a worked example of how to write a query that uses the location information provided in the database for finding likely bugs. - :doc:`AST class reference ` gives an overview of all AST classes in the standard CodeQL library for Java. From 0c9466640ab60622d46928f37a594b0ed82ea0cf Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 18 Mar 2020 16:26:30 +0000 Subject: [PATCH 100/459] C++: Add IR test for strcpy/strcat. --- .../library-tests/ir/ir/PrintAST.expected | 70 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ir/ir.cpp | 12 ++++ .../test/library-tests/ir/ir/raw_ir.expected | 56 +++++++++++++++ 3 files changed, 138 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 2be5a2019f8..d7ee37f3edf 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -8303,6 +8303,76 @@ ir.cpp: # 1219| Type = [IntType] int # 1219| ValueCategory = prvalue(load) # 1220| 4: [ReturnStmt] return ... +# 1224| [TopLevelFunction] char* strcpy(char*, char const*) +# 1224| params: +# 1224| 0: [Parameter] destination +# 1224| Type = [CharPointerType] char * +# 1224| 1: [Parameter] source +# 1224| Type = [PointerType] const char * +# 1225| [TopLevelFunction] char* strcat(char*, char const*) +# 1225| params: +# 1225| 0: [Parameter] destination +# 1225| Type = [CharPointerType] char * +# 1225| 1: [Parameter] source +# 1225| Type = [PointerType] const char * +# 1227| [TopLevelFunction] void test_strings(char*, char*) +# 1227| params: +# 1227| 0: [Parameter] s1 +# 1227| Type = [CharPointerType] char * +# 1227| 1: [Parameter] s2 +# 1227| Type = [CharPointerType] char * +# 1227| body: [Block] { ... } +# 1228| 0: [DeclStmt] declaration +# 1228| 0: [VariableDeclarationEntry] definition of buffer +# 1228| Type = [ArrayType] char[1024] +# 1228| init: [Initializer] initializer for buffer +# 1228| expr: [ArrayAggregateLiteral] {...} +# 1228| Type = [ArrayType] char[1024] +# 1228| ValueCategory = prvalue +# 1228| [0]: [CStyleCast] (char)... +# 1228| Conversion = [IntegralConversion] integral conversion +# 1228| Type = [PlainCharType] char +# 1228| Value = [CStyleCast] 0 +# 1228| ValueCategory = prvalue +# 1228| expr: [Literal] 0 +# 1228| Type = [IntType] int +# 1228| Value = [Literal] 0 +# 1228| ValueCategory = prvalue +# 1230| 1: [ExprStmt] ExprStmt +# 1230| 0: [FunctionCall] call to strcpy +# 1230| Type = [CharPointerType] char * +# 1230| ValueCategory = prvalue +# 1230| 0: [ArrayToPointerConversion] array to pointer conversion +# 1230| Type = [CharPointerType] char * +# 1230| ValueCategory = prvalue +# 1230| expr: [VariableAccess] buffer +# 1230| Type = [ArrayType] char[1024] +# 1230| ValueCategory = lvalue +# 1230| 1: [CStyleCast] (const char *)... +# 1230| Conversion = [PointerConversion] pointer conversion +# 1230| Type = [PointerType] const char * +# 1230| ValueCategory = prvalue +# 1230| expr: [VariableAccess] s1 +# 1230| Type = [CharPointerType] char * +# 1230| ValueCategory = prvalue(load) +# 1231| 2: [ExprStmt] ExprStmt +# 1231| 0: [FunctionCall] call to strcat +# 1231| Type = [CharPointerType] char * +# 1231| ValueCategory = prvalue +# 1231| 0: [ArrayToPointerConversion] array to pointer conversion +# 1231| Type = [CharPointerType] char * +# 1231| ValueCategory = prvalue +# 1231| expr: [VariableAccess] buffer +# 1231| Type = [ArrayType] char[1024] +# 1231| ValueCategory = lvalue +# 1231| 1: [CStyleCast] (const char *)... +# 1231| Conversion = [PointerConversion] pointer conversion +# 1231| Type = [PointerType] const char * +# 1231| ValueCategory = prvalue +# 1231| expr: [VariableAccess] s2 +# 1231| Type = [CharPointerType] char * +# 1231| ValueCategory = prvalue(load) +# 1232| 3: [ReturnStmt] return ... perf-regression.cpp: # 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&) # 4| params: diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index c3a394f0985..34a97710074 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1219,4 +1219,16 @@ void switch2Case_default(int x) { int z = y; } +// --- strings --- + +char *strcpy(char *destination, const char *source); +char *strcat(char *destination, const char *source); + +void test_strings(char *s1, char *s2) { + char buffer[1024] = {0}; + + strcpy(buffer, s1); + strcat(buffer, s2); +} + // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index f860574bb4c..2b199cb618e 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6228,6 +6228,62 @@ ir.cpp: # 1205| v1205_9(void) = AliasedUse : ~mu1205_4 # 1205| v1205_10(void) = ExitFunction : +# 1227| void test_strings(char*, char*) +# 1227| Block 0 +# 1227| v1227_1(void) = EnterFunction : +# 1227| mu1227_2(unknown) = AliasedDefinition : +# 1227| mu1227_3(unknown) = InitializeNonLocal : +# 1227| mu1227_4(unknown) = UnmodeledDefinition : +# 1227| r1227_5(glval) = VariableAddress[s1] : +# 1227| mu1227_6(char *) = InitializeParameter[s1] : &:r1227_5 +# 1227| r1227_7(char *) = Load : &:r1227_5, ~mu1227_6 +# 1227| mu1227_8(unknown) = InitializeIndirection[s1] : &:r1227_7 +# 1227| r1227_9(glval) = VariableAddress[s2] : +# 1227| mu1227_10(char *) = InitializeParameter[s2] : &:r1227_9 +# 1227| r1227_11(char *) = Load : &:r1227_9, ~mu1227_10 +# 1227| mu1227_12(unknown) = InitializeIndirection[s2] : &:r1227_11 +# 1228| r1228_1(glval) = VariableAddress[buffer] : +# 1228| mu1228_2(char[1024]) = Uninitialized[buffer] : &:r1228_1 +# 1228| r1228_3(int) = Constant[0] : +# 1228| r1228_4(glval) = PointerAdd[1] : r1228_1, r1228_3 +# 1228| r1228_5(char) = Constant[0] : +# 1228| mu1228_6(char) = Store : &:r1228_4, r1228_5 +# 1228| r1228_7(int) = Constant[1] : +# 1228| r1228_8(glval) = PointerAdd[1] : r1228_1, r1228_7 +# 1228| r1228_9(unknown[1023]) = Constant[0] : +# 1228| mu1228_10(unknown[1023]) = Store : &:r1228_8, r1228_9 +# 1230| r1230_1(glval) = FunctionAddress[strcpy] : +# 1230| r1230_2(glval) = VariableAddress[buffer] : +# 1230| r1230_3(char *) = Convert : r1230_2 +# 1230| r1230_4(glval) = VariableAddress[s1] : +# 1230| r1230_5(char *) = Load : &:r1230_4, ~mu1227_4 +# 1230| r1230_6(char *) = Convert : r1230_5 +# 1230| r1230_7(char *) = Call : func:r1230_1, 0:r1230_3, 1:r1230_6 +# 1230| mu1230_8(unknown) = ^CallSideEffect : ~mu1227_4 +# 1230| v1230_9(void) = ^BufferReadSideEffect[0] : &:r1230_3, ~mu1227_4 +# 1230| v1230_10(void) = ^BufferReadSideEffect[1] : &:r1230_6, ~mu1227_4 +# 1230| mu1230_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1230_3 +# 1230| mu1230_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1230_6 +# 1231| r1231_1(glval) = FunctionAddress[strcat] : +# 1231| r1231_2(glval) = VariableAddress[buffer] : +# 1231| r1231_3(char *) = Convert : r1231_2 +# 1231| r1231_4(glval) = VariableAddress[s2] : +# 1231| r1231_5(char *) = Load : &:r1231_4, ~mu1227_4 +# 1231| r1231_6(char *) = Convert : r1231_5 +# 1231| r1231_7(char *) = Call : func:r1231_1, 0:r1231_3, 1:r1231_6 +# 1231| mu1231_8(unknown) = ^CallSideEffect : ~mu1227_4 +# 1231| v1231_9(void) = ^BufferReadSideEffect[0] : &:r1231_3, ~mu1227_4 +# 1231| v1231_10(void) = ^BufferReadSideEffect[1] : &:r1231_6, ~mu1227_4 +# 1231| mu1231_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1231_3 +# 1231| mu1231_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1231_6 +# 1232| v1232_1(void) = NoOp : +# 1227| v1227_13(void) = ReturnIndirection : &:r1227_7, ~mu1227_4 +# 1227| v1227_14(void) = ReturnIndirection : &:r1227_11, ~mu1227_4 +# 1227| v1227_15(void) = ReturnVoid : +# 1227| v1227_16(void) = UnmodeledUse : mu* +# 1227| v1227_17(void) = AliasedUse : ~mu1227_4 +# 1227| v1227_18(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0 From 935b8d96f8df153233513ec274cf8584bcfa9536 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 18 Mar 2020 16:39:22 +0000 Subject: [PATCH 101/459] C++: Offset .expected for cleaner diff. --- .../test/library-tests/ir/ir/raw_ir.expected | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 2b199cb618e..3c10bd83d7f 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6230,59 +6230,59 @@ ir.cpp: # 1227| void test_strings(char*, char*) # 1227| Block 0 -# 1227| v1227_1(void) = EnterFunction : -# 1227| mu1227_2(unknown) = AliasedDefinition : -# 1227| mu1227_3(unknown) = InitializeNonLocal : -# 1227| mu1227_4(unknown) = UnmodeledDefinition : -# 1227| r1227_5(glval) = VariableAddress[s1] : -# 1227| mu1227_6(char *) = InitializeParameter[s1] : &:r1227_5 -# 1227| r1227_7(char *) = Load : &:r1227_5, ~mu1227_6 -# 1227| mu1227_8(unknown) = InitializeIndirection[s1] : &:r1227_7 -# 1227| r1227_9(glval) = VariableAddress[s2] : -# 1227| mu1227_10(char *) = InitializeParameter[s2] : &:r1227_9 -# 1227| r1227_11(char *) = Load : &:r1227_9, ~mu1227_10 -# 1227| mu1227_12(unknown) = InitializeIndirection[s2] : &:r1227_11 -# 1228| r1228_1(glval) = VariableAddress[buffer] : -# 1228| mu1228_2(char[1024]) = Uninitialized[buffer] : &:r1228_1 -# 1228| r1228_3(int) = Constant[0] : -# 1228| r1228_4(glval) = PointerAdd[1] : r1228_1, r1228_3 -# 1228| r1228_5(char) = Constant[0] : -# 1228| mu1228_6(char) = Store : &:r1228_4, r1228_5 -# 1228| r1228_7(int) = Constant[1] : -# 1228| r1228_8(glval) = PointerAdd[1] : r1228_1, r1228_7 -# 1228| r1228_9(unknown[1023]) = Constant[0] : -# 1228| mu1228_10(unknown[1023]) = Store : &:r1228_8, r1228_9 -# 1230| r1230_1(glval) = FunctionAddress[strcpy] : -# 1230| r1230_2(glval) = VariableAddress[buffer] : -# 1230| r1230_3(char *) = Convert : r1230_2 -# 1230| r1230_4(glval) = VariableAddress[s1] : -# 1230| r1230_5(char *) = Load : &:r1230_4, ~mu1227_4 -# 1230| r1230_6(char *) = Convert : r1230_5 -# 1230| r1230_7(char *) = Call : func:r1230_1, 0:r1230_3, 1:r1230_6 -# 1230| mu1230_8(unknown) = ^CallSideEffect : ~mu1227_4 -# 1230| v1230_9(void) = ^BufferReadSideEffect[0] : &:r1230_3, ~mu1227_4 -# 1230| v1230_10(void) = ^BufferReadSideEffect[1] : &:r1230_6, ~mu1227_4 -# 1230| mu1230_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1230_3 -# 1230| mu1230_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1230_6 -# 1231| r1231_1(glval) = FunctionAddress[strcat] : -# 1231| r1231_2(glval) = VariableAddress[buffer] : -# 1231| r1231_3(char *) = Convert : r1231_2 -# 1231| r1231_4(glval) = VariableAddress[s2] : -# 1231| r1231_5(char *) = Load : &:r1231_4, ~mu1227_4 -# 1231| r1231_6(char *) = Convert : r1231_5 -# 1231| r1231_7(char *) = Call : func:r1231_1, 0:r1231_3, 1:r1231_6 -# 1231| mu1231_8(unknown) = ^CallSideEffect : ~mu1227_4 -# 1231| v1231_9(void) = ^BufferReadSideEffect[0] : &:r1231_3, ~mu1227_4 -# 1231| v1231_10(void) = ^BufferReadSideEffect[1] : &:r1231_6, ~mu1227_4 -# 1231| mu1231_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1231_3 -# 1231| mu1231_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1231_6 -# 1232| v1232_1(void) = NoOp : -# 1227| v1227_13(void) = ReturnIndirection : &:r1227_7, ~mu1227_4 -# 1227| v1227_14(void) = ReturnIndirection : &:r1227_11, ~mu1227_4 -# 1227| v1227_15(void) = ReturnVoid : -# 1227| v1227_16(void) = UnmodeledUse : mu* -# 1227| v1227_17(void) = AliasedUse : ~mu1227_4 -# 1227| v1227_18(void) = ExitFunction : +# 1227| v1227_1(void) = EnterFunction : +# 1227| mu1227_2(unknown) = AliasedDefinition : +# 1227| mu1227_3(unknown) = InitializeNonLocal : +# 1227| mu1227_4(unknown) = UnmodeledDefinition : +# 1227| r1227_5(glval) = VariableAddress[s1] : +# 1227| mu1227_6(char *) = InitializeParameter[s1] : &:r1227_5 +# 1227| r1227_7(char *) = Load : &:r1227_5, ~mu1227_6 +# 1227| mu1227_8(unknown) = InitializeIndirection[s1] : &:r1227_7 +# 1227| r1227_9(glval) = VariableAddress[s2] : +# 1227| mu1227_10(char *) = InitializeParameter[s2] : &:r1227_9 +# 1227| r1227_11(char *) = Load : &:r1227_9, ~mu1227_10 +# 1227| mu1227_12(unknown) = InitializeIndirection[s2] : &:r1227_11 +# 1228| r1228_1(glval) = VariableAddress[buffer] : +# 1228| mu1228_2(char[1024]) = Uninitialized[buffer] : &:r1228_1 +# 1228| r1228_3(int) = Constant[0] : +# 1228| r1228_4(glval) = PointerAdd[1] : r1228_1, r1228_3 +# 1228| r1228_5(char) = Constant[0] : +# 1228| mu1228_6(char) = Store : &:r1228_4, r1228_5 +# 1228| r1228_7(int) = Constant[1] : +# 1228| r1228_8(glval) = PointerAdd[1] : r1228_1, r1228_7 +# 1228| r1228_9(unknown[1023]) = Constant[0] : +# 1228| mu1228_10(unknown[1023]) = Store : &:r1228_8, r1228_9 +# 1230| r1230_1(glval) = FunctionAddress[strcpy] : +# 1230| r1230_2(glval) = VariableAddress[buffer] : +# 1230| r1230_3(char *) = Convert : r1230_2 +# 1230| r1230_4(glval) = VariableAddress[s1] : +# 1230| r1230_5(char *) = Load : &:r1230_4, ~mu1227_4 +# 1230| r1230_6(char *) = Convert : r1230_5 +# 1230| r1230_7(char *) = Call : func:r1230_1, 0:r1230_3, 1:r1230_6 +# 1230| mu1230_8(unknown) = ^CallSideEffect : ~mu1227_4 +# 1230| v1230_9(void) = ^BufferReadSideEffect[0] : &:r1230_3, ~mu1227_4 +# 1230| v1230_10(void) = ^BufferReadSideEffect[1] : &:r1230_6, ~mu1227_4 +# 1230| mu1230_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1230_3 +# 1230| mu1230_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1230_6 +# 1231| r1231_1(glval) = FunctionAddress[strcat] : +# 1231| r1231_2(glval) = VariableAddress[buffer] : +# 1231| r1231_3(char *) = Convert : r1231_2 +# 1231| r1231_4(glval) = VariableAddress[s2] : +# 1231| r1231_5(char *) = Load : &:r1231_4, ~mu1227_4 +# 1231| r1231_6(char *) = Convert : r1231_5 +# 1231| r1231_7(char *) = Call : func:r1231_1, 0:r1231_3, 1:r1231_6 +# 1231| mu1231_8(unknown) = ^CallSideEffect : ~mu1227_4 +# 1231| v1231_9(void) = ^BufferReadSideEffect[0] : &:r1231_3, ~mu1227_4 +# 1231| v1231_10(void) = ^BufferReadSideEffect[1] : &:r1231_6, ~mu1227_4 +# 1231| mu1231_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1231_3 +# 1231| mu1231_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1231_6 +# 1232| v1232_1(void) = NoOp : +# 1227| v1227_13(void) = ReturnIndirection : &:r1227_7, ~mu1227_4 +# 1227| v1227_14(void) = ReturnIndirection : &:r1227_11, ~mu1227_4 +# 1227| v1227_15(void) = ReturnVoid : +# 1227| v1227_16(void) = UnmodeledUse : mu* +# 1227| v1227_17(void) = AliasedUse : ~mu1227_4 +# 1227| v1227_18(void) = ExitFunction : perf-regression.cpp: # 6| void Big::Big() From 6cc1c2341c8272c341c369995d9263518cc8e0f0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 18 Mar 2020 12:53:35 +0000 Subject: [PATCH 102/459] C++: Add some SideEffect models. --- .../cpp/models/implementations/Strcat.qll | 18 ++++++++++++++- .../cpp/models/implementations/Strcpy.qll | 22 ++++++++++++++++++- .../test/library-tests/ir/ir/raw_ir.expected | 15 +++++-------- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll index d56ebf10bbc..998329a3e47 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll @@ -1,11 +1,12 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.SideEffect /** * The standard function `strcat` and its wide, sized, and Microsoft variants. */ -class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction { +class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction { StrcatFunction() { exists(string name | name = getName() | name = "strcat" or // strcat(dst, src) @@ -56,4 +57,19 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction { override predicate hasArrayWithNullTerminator(int param) { param = 1 } override predicate hasArrayWithUnknownSize(int param) { param = 0 } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + i = 0 and + buffer = true and + mustWrite = false + } + + predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + (i = 0 or i = 1) and + buffer = true + } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index d4d7bcf2881..5fd59e1df54 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -1,11 +1,12 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.SideEffect /** * The standard function `strcpy` and its wide, sized, and Microsoft variants. */ -class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { +class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { StrcpyFunction() { this.hasName("strcpy") or this.hasName("_mbscpy") or @@ -74,4 +75,23 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { output.isReturnValueDeref() ) } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + i = 0 and + buffer = true and + mustWrite = true + } + + predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + i = 1 and + buffer = true + } + + ParameterIndex getParameterSizeIndex(ParameterIndex i) { + hasArrayWithVariableSize(i, result) + } } diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 3c10bd83d7f..eb8bdec2a46 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6259,11 +6259,8 @@ ir.cpp: # 1230| r1230_5(char *) = Load : &:r1230_4, ~mu1227_4 # 1230| r1230_6(char *) = Convert : r1230_5 # 1230| r1230_7(char *) = Call : func:r1230_1, 0:r1230_3, 1:r1230_6 -# 1230| mu1230_8(unknown) = ^CallSideEffect : ~mu1227_4 -# 1230| v1230_9(void) = ^BufferReadSideEffect[0] : &:r1230_3, ~mu1227_4 -# 1230| v1230_10(void) = ^BufferReadSideEffect[1] : &:r1230_6, ~mu1227_4 -# 1230| mu1230_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1230_3 -# 1230| mu1230_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1230_6 +# 1230| v1230_8(void) = ^BufferReadSideEffect[1] : &:r1230_6, ~mu1227_4 +# 1230| mu1230_9(unknown) = ^BufferMustWriteSideEffect[0] : &:r1230_3 # 1231| r1231_1(glval) = FunctionAddress[strcat] : # 1231| r1231_2(glval) = VariableAddress[buffer] : # 1231| r1231_3(char *) = Convert : r1231_2 @@ -6271,11 +6268,9 @@ ir.cpp: # 1231| r1231_5(char *) = Load : &:r1231_4, ~mu1227_4 # 1231| r1231_6(char *) = Convert : r1231_5 # 1231| r1231_7(char *) = Call : func:r1231_1, 0:r1231_3, 1:r1231_6 -# 1231| mu1231_8(unknown) = ^CallSideEffect : ~mu1227_4 -# 1231| v1231_9(void) = ^BufferReadSideEffect[0] : &:r1231_3, ~mu1227_4 -# 1231| v1231_10(void) = ^BufferReadSideEffect[1] : &:r1231_6, ~mu1227_4 -# 1231| mu1231_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1231_3 -# 1231| mu1231_12(unknown) = ^BufferMayWriteSideEffect[1] : &:r1231_6 +# 1231| v1231_8(void) = ^BufferReadSideEffect[0] : &:r1231_3, ~mu1227_4 +# 1231| v1231_9(void) = ^BufferReadSideEffect[1] : &:r1231_6, ~mu1227_4 +# 1231| mu1231_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1231_3 # 1232| v1232_1(void) = NoOp : # 1227| v1227_13(void) = ReturnIndirection : &:r1227_7, ~mu1227_4 # 1227| v1227_14(void) = ReturnIndirection : &:r1227_11, ~mu1227_4 From f32e84b1d0a2253b6df496346c591e5aace22372 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 18 Mar 2020 17:24:46 +0000 Subject: [PATCH 103/459] C++: Autoformat. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index 5fd59e1df54..80bc9ef29db 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -91,7 +91,5 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid buffer = true } - ParameterIndex getParameterSizeIndex(ParameterIndex i) { - hasArrayWithVariableSize(i, result) - } + ParameterIndex getParameterSizeIndex(ParameterIndex i) { hasArrayWithVariableSize(i, result) } } From b444383ed19c6fcea253d4df9abb9fa72a1630cb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 19 Mar 2020 13:09:37 +0000 Subject: [PATCH 104/459] C++: Add 'override' specifiers where I missed them. --- .../src/semmle/code/cpp/models/implementations/Strcpy.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index 80bc9ef29db..aceda0584ad 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -80,16 +80,16 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid override predicate hasOnlySpecificWriteSideEffects() { any() } - predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { i = 0 and buffer = true and mustWrite = true } - predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { i = 1 and buffer = true } - ParameterIndex getParameterSizeIndex(ParameterIndex i) { hasArrayWithVariableSize(i, result) } + override ParameterIndex getParameterSizeIndex(ParameterIndex i) { hasArrayWithVariableSize(i, result) } } From 88193dd389e7faf1193992aa9bcdb4f8554cc82d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 19 Mar 2020 13:32:17 +0000 Subject: [PATCH 105/459] C++: .expected change (desirable). --- .../StrncpyFlippedArgs/StrncpyFlippedArgs.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StrncpyFlippedArgs/StrncpyFlippedArgs.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StrncpyFlippedArgs/StrncpyFlippedArgs.expected index 0fe37d1fe05..d9756787518 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StrncpyFlippedArgs/StrncpyFlippedArgs.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StrncpyFlippedArgs/StrncpyFlippedArgs.expected @@ -12,5 +12,6 @@ | test.cpp:46:2:46:9 | call to strcpy_s | Potentially unsafe call to strcpy_s; second argument should be size of destination. | | test.cpp:47:2:47:9 | call to strcpy_s | Potentially unsafe call to strcpy_s; second argument should be size of destination. | | test.cpp:60:3:60:9 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. | +| test.cpp:63:3:63:9 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. | | test.cpp:68:2:68:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. | | test.cpp:79:3:79:9 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. | From 9e117709bcc8efcb76000a93030c22663b8184a4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 20 Mar 2020 14:59:57 +0000 Subject: [PATCH 106/459] C++: mustwrite = false. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index aceda0584ad..723e424263f 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -83,7 +83,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { i = 0 and buffer = true and - mustWrite = true + mustWrite = false } override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { From ccf5e03fc857050f89e4db1d68586dcd40d1a9e2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 20 Mar 2020 15:01:22 +0000 Subject: [PATCH 107/459] C++: Autoformat. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index 723e424263f..c7f0898f358 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -91,5 +91,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid buffer = true } - override ParameterIndex getParameterSizeIndex(ParameterIndex i) { hasArrayWithVariableSize(i, result) } + override ParameterIndex getParameterSizeIndex(ParameterIndex i) { + hasArrayWithVariableSize(i, result) + } } From 165dcd37a1922b054605b10ddb84147f3509dcd0 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:35:37 +0100 Subject: [PATCH 108/459] Python: Autoformat `library-tests`. --- .../PointsTo/general/interesting.qll | 3 +- .../test/library-tests/PointsTo/new/Util.qll | 20 +- .../test/library-tests/state_tracking/Lib.qll | 21 +- .../library-tests/taint/collections/Taint.qll | 31 +-- .../library-tests/taint/config/TaintLib.qll | 130 ++---------- .../library-tests/taint/dataflow/Config.qll | 2 - .../taint/example/DilbertConfig.qll | 12 +- .../taint/extensions/ExtensionsLib.qll | 31 +-- .../library-tests/taint/general/TaintLib.qll | 188 ++++-------------- .../library-tests/taint/namedtuple/Taint.qll | 4 +- .../library-tests/taint/strings/Taint.qll | 42 +--- 11 files changed, 96 insertions(+), 388 deletions(-) diff --git a/python/ql/test/library-tests/PointsTo/general/interesting.qll b/python/ql/test/library-tests/PointsTo/general/interesting.qll index 2a5259dd176..f7c3e9d682d 100644 --- a/python/ql/test/library-tests/PointsTo/general/interesting.qll +++ b/python/ql/test/library-tests/PointsTo/general/interesting.qll @@ -1,4 +1,3 @@ - import python predicate of_interest(ControlFlowNode n, int line) { @@ -6,7 +5,7 @@ predicate of_interest(ControlFlowNode n, int line) { line = l.getStartLine() and f = l.getFile() and f.getName().matches("%test.py%") and - exists(Comment c | + exists(Comment c | c.getLocation().getStartLine() < line and c.getLocation().getFile() = f ) diff --git a/python/ql/test/library-tests/PointsTo/new/Util.qll b/python/ql/test/library-tests/PointsTo/new/Util.qll index af8645f8d94..f59a1a8dae1 100644 --- a/python/ql/test/library-tests/PointsTo/new/Util.qll +++ b/python/ql/test/library-tests/PointsTo/new/Util.qll @@ -13,12 +13,17 @@ string locate(Location l, string which) { } string repr(Object o) { - /* Do not show `unknownValue()` to keep noise levels down. + /* + * Do not show `unknownValue()` to keep noise levels down. * To show it add: * `o = unknownValue() and result = "*UNKNOWN VALUE*"` */ - not o instanceof StringObject and not o = undefinedVariable() and not o = theUnknownType() and - not o = theBoundMethodType() and result = o.toString() + + not o instanceof StringObject and + not o = undefinedVariable() and + not o = theUnknownType() and + not o = theBoundMethodType() and + result = o.toString() or o = undefinedVariable() and result = "*UNDEFINED*" or @@ -30,16 +35,15 @@ string repr(Object o) { o = theBoundMethodType() and result = "builtin-class method" } -predicate long_tuple(Value v) { - v.(TupleObjectInternal).length() > 3 -} +predicate long_tuple(Value v) { v.(TupleObjectInternal).length() > 3 } string vrepr(Value v) { /* Work around differing names in 2/3 */ not v = ObjectInternal::boundMethod() and - not long_tuple(v) and result = v.toString() + not long_tuple(v) and + result = v.toString() or v = ObjectInternal::boundMethod() and result = "builtin-class method" or long_tuple(v) and result = "(..., ...)" -} \ No newline at end of file +} diff --git a/python/ql/test/library-tests/state_tracking/Lib.qll b/python/ql/test/library-tests/state_tracking/Lib.qll index f2c0db3c296..e784b7e198b 100644 --- a/python/ql/test/library-tests/state_tracking/Lib.qll +++ b/python/ql/test/library-tests/state_tracking/Lib.qll @@ -1,31 +1,18 @@ import python import semmle.python.dataflow.StateTracking -predicate callTo(CallNode call, string name) { - call.getFunction().(NameNode).getId() = name -} +predicate callTo(CallNode call, string name) { call.getFunction().(NameNode).getId() = name } class Initialized extends TrackableState { - Initialized() { this = "initialized" } - override predicate startsAt(ControlFlowNode f) { - callTo(f, "initialize") - } - + override predicate startsAt(ControlFlowNode f) { callTo(f, "initialize") } } - class Frobnicated extends TrackableState { - Frobnicated() { this = "frobnicated" } - override predicate startsAt(ControlFlowNode f) { - callTo(f, "frobnicate") - } - - override predicate endsAt(ControlFlowNode f) { - callTo(f, "defrobnicate") - } + override predicate startsAt(ControlFlowNode f) { callTo(f, "frobnicate") } + override predicate endsAt(ControlFlowNode f) { callTo(f, "defrobnicate") } } diff --git a/python/ql/test/library-tests/taint/collections/Taint.qll b/python/ql/test/library-tests/taint/collections/Taint.qll index b61870722b8..b97f65225f2 100644 --- a/python/ql/test/library-tests/taint/collections/Taint.qll +++ b/python/ql/test/library-tests/taint/collections/Taint.qll @@ -2,45 +2,26 @@ import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted - class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringKind - } - - override string toString() { - result = "taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } + override string toString() { result = "taint source" } } class ListSource extends TaintSource { - ListSource() { this.(NameNode).getId() = "TAINTED_LIST" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringSequenceKind - } - - override string toString() { - result = "list taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind } + override string toString() { result = "list taint source" } } class DictSource extends TaintSource { - DictSource() { this.(NameNode).getId() = "TAINTED_DICT" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringDictKind - } - - override string toString() { - result = "dict taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind } + override string toString() { result = "dict taint source" } } diff --git a/python/ql/test/library-tests/taint/config/TaintLib.qll b/python/ql/test/library-tests/taint/config/TaintLib.qll index dd9a0186a35..670a9515c33 100644 --- a/python/ql/test/library-tests/taint/config/TaintLib.qll +++ b/python/ql/test/library-tests/taint/config/TaintLib.qll @@ -1,24 +1,16 @@ import python import semmle.python.security.TaintTracking - class SimpleTest extends TaintKind { - - SimpleTest() { - this = "simple.test" - } - + SimpleTest() { this = "simple.test" } } abstract class TestConfig extends TaintTracking::Configuration { - bindingset[this] TestConfig() { any() } - } class SimpleConfig extends TestConfig { - SimpleConfig() { this = "Simple config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -38,26 +30,19 @@ class SimpleConfig extends TestConfig { node.asCfgNode().(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and kind instanceof SimpleTest } - } class BasicCustomTaint extends TaintKind { - - BasicCustomTaint() { - this = "basic.custom" - } + BasicCustomTaint() { this = "basic.custom" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { tonode.(CallNode).getAnArg() = fromnode and tonode.(CallNode).getFunction().(NameNode).getId() = "TAINT_FROM_ARG" and result = this } - } - class BasicCustomConfig extends TestConfig { - BasicCustomConfig() { this = "Basic custom config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -72,57 +57,46 @@ class BasicCustomConfig extends TestConfig { ) and kind instanceof SimpleTest } - } - class Rock extends TaintKind { - Rock() { this = "rock" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Scissors } - } class Paper extends TaintKind { - Paper() { this = "paper" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Rock } - } class Scissors extends TaintKind { - Scissors() { this = "scissors" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Paper } - } class RockPaperScissorConfig extends TestConfig { - RockPaperScissorConfig() { this = "Rock-paper-scissors config" } - override predicate isSource(DataFlow::Node node, TaintKind kind) { exists(string name | node.asCfgNode().(NameNode).getId() = name and kind = name.toLowerCase() - | + | name = "ROCK" or name = "PAPER" or name = "SCISSORS" ) } override predicate isSink(DataFlow::Node node, TaintKind kind) { - exists(string name | - function_param(name, node) | + exists(string name | function_param(name, node) | name = "paper" and kind = "rock" or name = "rock" and kind = "scissors" @@ -130,7 +104,6 @@ class RockPaperScissorConfig extends TestConfig { name = "scissors" and kind = "paper" ) } - } private predicate function_param(string funcname, DataFlow::Node arg) { @@ -140,20 +113,15 @@ private predicate function_param(string funcname, DataFlow::Node arg) { ) } - class TaintCarrier extends TaintKind { - TaintCarrier() { this = "explicit.carrier" } override TaintKind getTaintOfMethodResult(string name) { name = "get_taint" and result instanceof SimpleTest } - - } class TaintCarrierConfig extends TestConfig { - TaintCarrierConfig() { this = "Taint carrier config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -173,49 +141,31 @@ class TaintCarrierConfig extends TestConfig { node.asCfgNode().(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and kind instanceof SimpleTest } - } - /* Some more realistic examples */ - abstract class UserInput extends TaintKind { - bindingset[this] UserInput() { any() } - } class UserInputSource extends TaintSource { + UserInputSource() { this.(CallNode).getFunction().(NameNode).getId() = "user_input" } - UserInputSource() { - this.(CallNode).getFunction().(NameNode).getId() = "user_input" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof UserInput - } - - override string toString() { - result = "user.input.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof UserInput } + override string toString() { result = "user.input.source" } } class SqlInjectionTaint extends UserInput { - SqlInjectionTaint() { this = "SQL injection" } - } class CommandInjectionTaint extends UserInput { - CommandInjectionTaint() { this = "Command injection" } - } class SqlSanitizer extends Sanitizer { - SqlSanitizer() { this = "SQL sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -229,11 +179,9 @@ class SqlSanitizer extends Sanitizer { ) and taint instanceof SqlInjectionTaint } - } class CommandSanitizer extends Sanitizer { - CommandSanitizer() { this = "Command sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -245,11 +193,9 @@ class CommandSanitizer extends Sanitizer { ) and taint instanceof CommandInjectionTaint } - } class SqlQuery extends TaintSink { - SqlQuery() { exists(CallNode call | call.getFunction().(NameNode).getId() = "sql_query" and @@ -259,15 +205,10 @@ class SqlQuery extends TaintSink { override string toString() { result = "SQL query" } - override predicate sinks(TaintKind taint) { - taint instanceof SqlInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof SqlInjectionTaint } } - class OsCommand extends TaintSink { - OsCommand() { exists(CallNode call | call.getFunction().(NameNode).getId() = "os_command" and @@ -277,60 +218,31 @@ class OsCommand extends TaintSink { override string toString() { result = "OS command" } - override predicate sinks(TaintKind taint) { - taint instanceof CommandInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof CommandInjectionTaint } } - class Falsey extends TaintKind { - Falsey() { this = "falsey" } - override boolean booleanValue() { - result = false - } - + override boolean booleanValue() { result = false } } -class FalseySource extends TaintSource { +class FalseySource extends TaintSource { + FalseySource() { this.(NameNode).getId() = "FALSEY" } - FalseySource() { - this.(NameNode).getId() = "FALSEY" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof Falsey - } - - override string toString() { - result = "falsey.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof Falsey } + override string toString() { result = "falsey.source" } } class TaintIterable extends TaintKind { + TaintIterable() { this = "iterable.simple" } - TaintIterable() { - this = "iterable.simple" - } - - override TaintKind getTaintForIteration() { - result instanceof SimpleTest - } - + override TaintKind getTaintForIteration() { result instanceof SimpleTest } } class TaintIterableSource extends TaintSource { + TaintIterableSource() { this.(NameNode).getId() = "ITERABLE_SOURCE" } - TaintIterableSource() { - this.(NameNode).getId() = "ITERABLE_SOURCE" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof TaintIterable - } - + override predicate isSourceOf(TaintKind kind) { kind instanceof TaintIterable } } - diff --git a/python/ql/test/library-tests/taint/dataflow/Config.qll b/python/ql/test/library-tests/taint/dataflow/Config.qll index 3d077f8c5b4..34a36dd9e1f 100644 --- a/python/ql/test/library-tests/taint/dataflow/Config.qll +++ b/python/ql/test/library-tests/taint/dataflow/Config.qll @@ -2,7 +2,6 @@ import python import semmle.python.dataflow.DataFlow class TestConfiguration extends DataFlow::Configuration { - TestConfiguration() { this = "Test configuration" } override predicate isSource(ControlFlowNode source) { source.(NameNode).getId() = "SOURCE" } @@ -13,5 +12,4 @@ class TestConfiguration extends DataFlow::Configuration { sink = call.getAnArg() ) } - } diff --git a/python/ql/test/library-tests/taint/example/DilbertConfig.qll b/python/ql/test/library-tests/taint/example/DilbertConfig.qll index 1628fcc394f..c54ea8060a3 100644 --- a/python/ql/test/library-tests/taint/example/DilbertConfig.qll +++ b/python/ql/test/library-tests/taint/example/DilbertConfig.qll @@ -1,6 +1,6 @@ /** * @kind path-problem - * + * * An example configuration. * See ExampleConfiguration.expected for the results of running this query. */ @@ -9,23 +9,16 @@ import python import semmle.python.dataflow.Configuration /* First of all we set up some TaintKinds */ - class Engineer extends TaintKind { - Engineer() { this = "Wally" or this = "Dilbert" } - } class Wally extends Engineer { - Wally() { this = "Wally" } - } /** Then the configuration */ - class DilbertConfig extends TaintTracking::Configuration { - DilbertConfig() { this = "Dilbert config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -46,11 +39,8 @@ class DilbertConfig extends TaintTracking::Configuration { /* Even the conscientious stop work if the building is on fire */ function_param("fire", node) } - } - - /** Helper predicate looking for `funcname(..., arg, ...)` */ private predicate function_param(string funcname, DataFlow::Node arg) { exists(Call call | diff --git a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll index 9cbbc6f9e2d..bc0534df455 100644 --- a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll +++ b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll @@ -1,17 +1,11 @@ import python - import semmle.python.security.TaintTracking class SimpleTest extends TaintKind { - - SimpleTest() { - this = "simple.test" - } - + SimpleTest() { this = "simple.test" } } class SimpleSink extends TaintSink { - override string toString() { result = "Simple sink" } SimpleSink() { @@ -21,27 +15,17 @@ class SimpleSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof SimpleTest - } - + override predicate sinks(TaintKind taint) { taint instanceof SimpleTest } } class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "SOURCE" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof SimpleTest - } - - override string toString() { - result = "simple.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof SimpleTest } + override string toString() { result = "simple.source" } } - predicate visit_call(CallNode call, FunctionObject func) { exists(AttrNode attr, ClassObject cls, string name | name.prefix(6) = "visit_" and @@ -52,9 +36,7 @@ predicate visit_call(CallNode call, FunctionObject func) { } /* Test call extensions by tracking taint through visitor methods */ - class TestCallReturnExtension extends DataFlowExtension::DataFlowNode { - TestCallReturnExtension() { exists(PyFunctionObject func | visit_call(_, func) and @@ -69,11 +51,9 @@ class TestCallReturnExtension extends DataFlowExtension::DataFlowNode { result = call ) } - } class TestCallParameterExtension extends DataFlowExtension::DataFlowNode { - TestCallParameterExtension() { exists(PyFunctionObject func, CallNode call | visit_call(call, func) and @@ -86,9 +66,8 @@ class TestCallParameterExtension extends DataFlowExtension::DataFlowNode { visit_call(call, func) and exists(int n | this = call.getArg(n) and - result.getNode() = func.getFunction().getArg(n+1) + result.getNode() = func.getFunction().getArg(n + 1) ) ) } - } diff --git a/python/ql/test/library-tests/taint/general/TaintLib.qll b/python/ql/test/library-tests/taint/general/TaintLib.qll index b3984b32976..9e4cbc31a89 100644 --- a/python/ql/test/library-tests/taint/general/TaintLib.qll +++ b/python/ql/test/library-tests/taint/general/TaintLib.qll @@ -1,17 +1,11 @@ import python import semmle.python.security.TaintTracking - class SimpleTest extends TaintKind { - - SimpleTest() { - this = "simple.test" - } - + SimpleTest() { this = "simple.test" } } class SimpleSink extends TaintSink { - override string toString() { result = "Simple sink" } SimpleSink() { @@ -21,31 +15,21 @@ class SimpleSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof SimpleTest - } - + override predicate sinks(TaintKind taint) { taint instanceof SimpleTest } } class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "SOURCE" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof SimpleTest - } - - override string toString() { - result = "simple.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof SimpleTest } + override string toString() { result = "simple.source" } } class SimpleSanitizer extends Sanitizer { - SimpleSanitizer() { this = "Simple sanitizer" } - override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) { + override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) { node.(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and taint instanceof SimpleTest } @@ -60,21 +44,16 @@ class SimpleSanitizer extends Sanitizer { } class BasicCustomTaint extends TaintKind { - - BasicCustomTaint() { - this = "basic.custom" - } + BasicCustomTaint() { this = "basic.custom" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { tonode.(CallNode).getAnArg() = fromnode and tonode.(CallNode).getFunction().(NameNode).getId() = "TAINT_FROM_ARG" and result = this } - } class BasicCustomSink extends TaintSink { - override string toString() { result = "Basic custom sink" } BasicCustomSink() { @@ -84,32 +63,21 @@ class BasicCustomSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof BasicCustomTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof BasicCustomTaint } } - class BasicCustomSource extends TaintSource { - BasicCustomSource() { this.(NameNode).getId() = "CUSTOM_SOURCE" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof BasicCustomTaint - } - - override string toString() { - result = "basic.custom.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof BasicCustomTaint } + override string toString() { result = "basic.custom.source" } } class Rock extends TaintKind { - Rock() { this = "rock" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Scissors } @@ -119,31 +87,27 @@ class Rock extends TaintKind { call.getFunction().(NameNode).getId() = "paper" ) } - } class Paper extends TaintKind { - Paper() { this = "paper" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Rock } - predicate isSink(ControlFlowNode sink) { + predicate isSink(ControlFlowNode sink) { exists(CallNode call | call.getArg(0) = sink and call.getFunction().(NameNode).getId() = "scissors" ) } - } class Scissors extends TaintKind { - Scissors() { this = "scissors" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Paper } @@ -153,26 +117,18 @@ class Scissors extends TaintKind { call.getFunction().(NameNode).getId() = "rock" ) } - } class RockPaperScissorSource extends TaintSource { - - RockPaperScissorSource() { - exists(string name | - this.(NameNode).getId() = name | + RockPaperScissorSource() { + exists(string name | this.(NameNode).getId() = name | name = "ROCK" or name = "PAPER" or name = "SCISSORS" ) } - override predicate isSourceOf(TaintKind kind) { - kind = this.(NameNode).getId().toLowerCase() - } - - override string toString() { - result = "rock.paper.scissors.source" - } + override predicate isSourceOf(TaintKind kind) { kind = this.(NameNode).getId().toLowerCase() } + override string toString() { result = "rock.paper.scissors.source" } } private predicate function_param(string funcname, ControlFlowNode arg) { @@ -183,17 +139,14 @@ private predicate function_param(string funcname, ControlFlowNode arg) { } class RockPaperScissorSink extends TaintSink { - RockPaperScissorSink() { - exists(string name | - function_param(name, this) | + exists(string name | function_param(name, this) | name = "rock" or name = "paper" or name = "scissors" ) } override predicate sinks(TaintKind taint) { - exists(string name | - function_param(name, this) | + exists(string name | function_param(name, this) | name = "paper" and taint = "rock" or name = "rock" and taint = "scissors" @@ -202,79 +155,49 @@ class RockPaperScissorSink extends TaintSink { ) } - override string toString() { - result = "rock.paper.scissors.sink" - } - + override string toString() { result = "rock.paper.scissors.sink" } } class TaintCarrier extends TaintKind { - TaintCarrier() { this = "explicit.carrier" } override TaintKind getTaintOfMethodResult(string name) { name = "get_taint" and result instanceof SimpleTest } - - } /* There is no sink for `TaintCarrier`. It is not "dangerous" in itself; it merely holds a `SimpleTest`. */ class TaintCarrierSource extends TaintSource { + TaintCarrierSource() { this.(NameNode).getId() = "TAINT_CARRIER_SOURCE" } - TaintCarrierSource() { - this.(NameNode).getId() = "TAINT_CARRIER_SOURCE" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof TaintCarrier } - override predicate isSourceOf(TaintKind kind) { - kind instanceof TaintCarrier - } - - override string toString() { - result = "taint.carrier.source" - } + override string toString() { result = "taint.carrier.source" } } - /* Some more realistic examples */ - abstract class UserInput extends TaintKind { - bindingset[this] UserInput() { any() } - } class UserInputSource extends TaintSource { + UserInputSource() { this.(CallNode).getFunction().(NameNode).getId() = "user_input" } - UserInputSource() { - this.(CallNode).getFunction().(NameNode).getId() = "user_input" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof UserInput - } - - override string toString() { - result = "user.input.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof UserInput } + override string toString() { result = "user.input.source" } } class SqlInjectionTaint extends UserInput { - SqlInjectionTaint() { this = "SQL injection" } - } class CommandInjectionTaint extends UserInput { - CommandInjectionTaint() { this = "Command injection" } - } class SqlSanitizer extends Sanitizer { - SqlSanitizer() { this = "SQL sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -288,11 +211,9 @@ class SqlSanitizer extends Sanitizer { ) and taint instanceof SqlInjectionTaint } - } class CommandSanitizer extends Sanitizer { - CommandSanitizer() { this = "Command sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -304,11 +225,9 @@ class CommandSanitizer extends Sanitizer { ) and taint instanceof CommandInjectionTaint } - } class SqlQuery extends TaintSink { - SqlQuery() { exists(CallNode call | call.getFunction().(NameNode).getId() = "sql_query" and @@ -318,15 +237,10 @@ class SqlQuery extends TaintSink { override string toString() { result = "SQL query" } - override predicate sinks(TaintKind taint) { - taint instanceof SqlInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof SqlInjectionTaint } } - class OsCommand extends TaintSink { - OsCommand() { exists(CallNode call | call.getFunction().(NameNode).getId() = "os_command" and @@ -336,59 +250,31 @@ class OsCommand extends TaintSink { override string toString() { result = "OS command" } - override predicate sinks(TaintKind taint) { - taint instanceof CommandInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof CommandInjectionTaint } } - class Falsey extends TaintKind { - Falsey() { this = "falsey" } - override boolean booleanValue() { - result = false - } - + override boolean booleanValue() { result = false } } -class FalseySource extends TaintSource { +class FalseySource extends TaintSource { + FalseySource() { this.(NameNode).getId() = "FALSEY" } - FalseySource() { - this.(NameNode).getId() = "FALSEY" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof Falsey - } - - override string toString() { - result = "falsey.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof Falsey } + override string toString() { result = "falsey.source" } } class TaintIterable extends TaintKind { + TaintIterable() { this = "iterable.simple" } - TaintIterable() { - this = "iterable.simple" - } - - override TaintKind getTaintForIteration() { - result instanceof SimpleTest - } - + override TaintKind getTaintForIteration() { result instanceof SimpleTest } } class TaintIterableSource extends TaintSource { + TaintIterableSource() { this.(NameNode).getId() = "ITERABLE_SOURCE" } - TaintIterableSource() { - this.(NameNode).getId() = "ITERABLE_SOURCE" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof TaintIterable - } - + override predicate isSourceOf(TaintKind kind) { kind instanceof TaintIterable } } diff --git a/python/ql/test/library-tests/taint/namedtuple/Taint.qll b/python/ql/test/library-tests/taint/namedtuple/Taint.qll index 9d19a54488c..580ed13f8f1 100644 --- a/python/ql/test/library-tests/taint/namedtuple/Taint.qll +++ b/python/ql/test/library-tests/taint/namedtuple/Taint.qll @@ -41,7 +41,5 @@ class TestConfig extends TaintTracking::Configuration { source instanceof DictSource } - override predicate isSink(TaintTracking::Sink sink) { - none() - } + override predicate isSink(TaintTracking::Sink sink) { none() } } diff --git a/python/ql/test/library-tests/taint/strings/Taint.qll b/python/ql/test/library-tests/taint/strings/Taint.qll index d045534e0ef..6c39426d161 100644 --- a/python/ql/test/library-tests/taint/strings/Taint.qll +++ b/python/ql/test/library-tests/taint/strings/Taint.qll @@ -3,60 +3,34 @@ import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.Exceptions - class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringKind - } - - override string toString() { - result = "taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } + override string toString() { result = "taint source" } } class ListSource extends TaintSource { - ListSource() { this.(NameNode).getId() = "TAINTED_LIST" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringSequenceKind - } - - override string toString() { - result = "list taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind } + override string toString() { result = "list taint source" } } class DictSource extends TaintSource { - DictSource() { this.(NameNode).getId() = "TAINTED_DICT" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringDictKind - } - - override string toString() { - result = "dict taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind } + override string toString() { result = "dict taint source" } } - class ExceptionInfoSource extends TaintSource { - ExceptionInfoSource() { this.(NameNode).getId() = "TAINTED_EXCEPTION_INFO" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionInfo - } - - override string toString() { - result = "Exception info source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfo } + override string toString() { result = "Exception info source" } } From d8b942f922a1a65044601257c9cc261de14ff58c Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:36:07 +0100 Subject: [PATCH 109/459] Python: Autoformat `objects`. --- .../src/semmle/python/objects/Callables.qll | 268 +++---- .../ql/src/semmle/python/objects/Classes.qll | 259 +++---- .../src/semmle/python/objects/Constants.qll | 245 ++----- .../src/semmle/python/objects/Descriptors.qll | 151 ++-- .../src/semmle/python/objects/Instances.qll | 297 ++++---- .../ql/src/semmle/python/objects/Modules.qll | 319 +++----- .../src/semmle/python/objects/ObjectAPI.qll | 682 +++++++----------- .../semmle/python/objects/ObjectInternal.qll | 436 +++++------ .../src/semmle/python/objects/Sequences.qll | 158 ++-- .../ql/src/semmle/python/objects/TObject.qll | 305 ++++---- 10 files changed, 1250 insertions(+), 1870 deletions(-) diff --git a/python/ql/src/semmle/python/objects/Callables.qll b/python/ql/src/semmle/python/objects/Callables.qll index 431d57bcfe7..b915e4bd5c2 100644 --- a/python/ql/src/semmle/python/objects/Callables.qll +++ b/python/ql/src/semmle/python/objects/Callables.qll @@ -1,6 +1,4 @@ - import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -8,9 +6,7 @@ private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins - abstract class CallableObjectInternal extends ObjectInternal { - /** Gets the scope of this callable if it has one */ abstract Function getScope(); @@ -26,7 +22,10 @@ abstract class CallableObjectInternal extends ObjectInternal { override ClassDecl getClassDeclaration() { none() } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } abstract NameNode getParameter(int n); @@ -36,11 +35,11 @@ abstract class CallableObjectInternal extends ObjectInternal { override int length() { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } @@ -50,12 +49,10 @@ abstract class CallableObjectInternal extends ObjectInternal { /* Callables aren't iterable */ override ObjectInternal getIterNext() { none() } - } /** Class representing Python functions */ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFunctionObject { - override Function getScope() { exists(CallableExpr expr | this = TPythonFunctionObject(expr.getAFlowNode()) and @@ -63,9 +60,7 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti ) } - override string toString() { - result = "Function " + this.getScope().getQualifiedName() - } + override string toString() { result = "Function " + this.getScope().getQualifiedName() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TPythonFunctionObject(node) and context.appliesTo(node) @@ -77,19 +72,16 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti override predicate notTestableForEquality() { none() } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TPythonFunctionObject(result) - } + override ControlFlowNode getOrigin() { this = TPythonFunctionObject(result) } - pragma [nomagic] + pragma[nomagic] override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { exists(Function func, ControlFlowNode rval, ControlFlowNode forigin | func = this.getScope() and - callee.appliesToScope(func) | + callee.appliesToScope(func) + | rval = func.getAReturnValueFlowNode() and PointsToInternal::pointsTo(rval, callee, obj, forigin) and origin = CfgOrigin::fromCfgNode(forigin) @@ -98,17 +90,20 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti procedureReturnsNone(callee, obj, origin) } - private predicate procedureReturnsNone(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + private predicate procedureReturnsNone( + PointsToContext callee, ObjectInternal obj, CfgOrigin origin + ) { exists(Function func | func = this.getScope() and - callee.appliesToScope(func) | + callee.appliesToScope(func) + | PointsToInternal::reachableBlock(blockReturningNone(func), callee) and obj = ObjectInternal::none_() and origin = CfgOrigin::unknown() ) } - pragma [noinline] + pragma[noinline] override predicate callResult(ObjectInternal obj, CfgOrigin origin) { this.getScope().isProcedure() and obj = ObjectInternal::none_() and @@ -119,41 +114,37 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti scope = this.getScope() and paramOffset = 0 } - override string getName() { - result = this.getScope().getName() - } + override string getName() { result = this.getScope().getName() } override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this and origin = CfgOrigin::fromCfgNode(this.getOrigin()) + value = this and + origin = CfgOrigin::fromCfgNode(this.getOrigin()) } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { value = TBoundMethod(instance, this) and origin = CfgOrigin::unknown() } override CallNode getACall(PointsToContext ctx) { PointsTo::pointsTo(result.getFunction(), ctx, this, _) or - exists(BoundMethodObjectInternal bm | - bm.getACall(ctx) = result and this = bm.getFunction() - ) + exists(BoundMethodObjectInternal bm | bm.getACall(ctx) = result and this = bm.getFunction()) } - override NameNode getParameter(int n) { - result.getNode() = this.getScope().getArg(n) - } + override NameNode getParameter(int n) { result.getNode() = this.getScope().getArg(n) } override NameNode getParameterByName(string name) { result.getNode() = this.getScope().getArgByName(name) } - - override predicate neverReturns() { - InterProceduralPointsTo::neverReturns(this.getScope()) - } + override predicate neverReturns() { InterProceduralPointsTo::neverReturns(this.getScope()) } override predicate functionAndOffset(CallableObjectInternal function, int offset) { function = this and offset = 0 @@ -164,10 +155,8 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } - private BasicBlock blockReturningNone(Function func) { exists(Return ret | not exists(ret.getValue()) and @@ -176,38 +165,31 @@ private BasicBlock blockReturningNone(Function func) { ) } - /** Class representing built-in functions such as `len` or `print`. */ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunctionObject { + override Builtin getBuiltin() { this = TBuiltinFunctionObject(result) } - override Builtin getBuiltin() { - this = TBuiltinFunctionObject(result) - } + override string toString() { result = "Builtin-function " + this.getBuiltin().getName() } - override string toString() { - result = "Builtin-function " + this.getBuiltin().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } - - override ObjectInternal getClass() { - result = TBuiltinClassObject(this.getBuiltin().getClass()) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) } override predicate notTestableForEquality() { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - pragma [noinline] + pragma[noinline] override predicate callResult(ObjectInternal obj, CfgOrigin origin) { exists(Builtin func, BuiltinClassObjectInternal cls | func = this.getBuiltin() and func != Builtin::builtin("isinstance") and func != Builtin::builtin("issubclass") and func != Builtin::builtin("callable") and - cls = ObjectInternal::fromBuiltin(this.getReturnType()) | + cls = ObjectInternal::fromBuiltin(this.getReturnType()) + | obj = TUnknownInstance(cls) or cls = ObjectInternal::noneType() and obj = ObjectInternal::none_() @@ -221,17 +203,11 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override string getName() { - result = this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } Builtin getReturnType() { exists(Builtin func | @@ -251,21 +227,25 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } override CallNode getACall(PointsToContext ctx) { PointsTo::pointsTo(result.getFunction(), ctx, this, _) } - override NameNode getParameter(int n) { - none() - } + override NameNode getParameter(int n) { none() } - override NameNode getParameterByName(string name) { - none() - } + override NameNode getParameterByName(string name) { none() } override predicate neverReturns() { exists(ModuleObjectInternal sys | @@ -283,7 +263,6 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } private Builtin getBuiltinFunctionReturnType(Builtin func) { @@ -297,7 +276,8 @@ private Builtin getBuiltinFunctionReturnType(Builtin func) { func = Builtin::builtin("__import__") and result = Builtin::special("ModuleType") or /* Fix a few minor inaccuracies in the CPython analysis */ - ext_rettype(func, result) and not ( + ext_rettype(func, result) and + not ( func = Builtin::builtin("__import__") or func = Builtin::builtin("compile") and result = Builtin::special("NoneType") @@ -309,34 +289,27 @@ private Builtin getBuiltinFunctionReturnType(Builtin func) { } /** Class representing methods of built-in classes (otherwise known as method-descriptors) such as `list.append`. */ - class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethodObject { + override Builtin getBuiltin() { this = TBuiltinMethodObject(result) } - override Builtin getBuiltin() { - this = TBuiltinMethodObject(result) - } + override string toString() { result = "builtin method " + this.getBuiltin().getName() } - override string toString() { - result = "builtin method " + this.getBuiltin().getName() - } + override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) } - override ObjectInternal getClass() { - result = TBuiltinClassObject(this.getBuiltin().getClass()) - } - - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - pragma [noinline] + pragma[noinline] override predicate callResult(ObjectInternal obj, CfgOrigin origin) { exists(Builtin func, BuiltinClassObjectInternal cls | func = this.getBuiltin() and - cls = ObjectInternal::fromBuiltin(this.getReturnType()) | + cls = ObjectInternal::fromBuiltin(this.getReturnType()) + | obj = TUnknownInstance(cls) or cls = ObjectInternal::noneType() and obj = ObjectInternal::none_() @@ -352,41 +325,34 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod Builtin getReturnType() { /* If we have a record of the return type in our stubs, use that. */ - exists(Builtin func | - func = this.getBuiltin() | - ext_rettype(func, result) - ) + exists(Builtin func | func = this.getBuiltin() | ext_rettype(func, result)) } private predicate returnTypeUnknown() { - exists(Builtin func | - func = this.getBuiltin() | - not ext_rettype(func, _) - ) + exists(Builtin func | func = this.getBuiltin() | not ext_rettype(func, _)) } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override string getName() { - result = this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } override Function getScope() { none() } override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this and origin = CfgOrigin::unknown() + value = this and + origin = CfgOrigin::unknown() } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { value = TBoundMethod(instance, this) and origin = CfgOrigin::unknown() } @@ -394,13 +360,9 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod PointsTo::pointsTo(result.getFunction(), ctx, this, _) } - override NameNode getParameter(int n) { - none() - } + override NameNode getParameter(int n) { none() } - override NameNode getParameterByName(string name) { - none() - } + override NameNode getParameterByName(string name) { none() } override predicate neverReturns() { none() } @@ -413,27 +375,20 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } -/** Class representing bound-methods. +/** + * Class representing bound-methods. * Note that built-in methods, such as `[].append` are also represented as bound-methods. * Although built-in methods and bound-methods are distinct classes in CPython, their behaviour * is the same and we treat them identically. */ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } + CallableObjectInternal getFunction() { this = TBoundMethod(_, result) } - CallableObjectInternal getFunction() { - this = TBoundMethod(_, result) - } - - ObjectInternal getSelf() { - this = TBoundMethod(result, _) - } + ObjectInternal getSelf() { this = TBoundMethod(result, _) } override string toString() { result = "Method(" + this.getFunction() + ", " + this.getSelf() + ")" @@ -443,9 +398,7 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { result = TBuiltinClassObject(Builtin::special("MethodType")) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } @@ -457,43 +410,41 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { this.getFunction().callResult(obj, origin) } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate calleeAndOffset(Function scope, int paramOffset) { - this.getFunction().calleeAndOffset(scope, paramOffset-1) + this.getFunction().calleeAndOffset(scope, paramOffset - 1) } - override string getName() { - result = this.getFunction().getName() - } + override string getName() { result = this.getFunction().getName() } - override Function getScope() { - result = this.getFunction().getScope() - } + override Function getScope() { result = this.getFunction().getScope() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } override CallNode getACall(PointsToContext ctx) { PointsTo::pointsTo(result.getFunction(), ctx, this, _) } - override NameNode getParameter(int n) { - result = this.getFunction().getParameter(n+1) - } + override NameNode getParameter(int n) { result = this.getFunction().getParameter(n + 1) } override NameNode getParameterByName(string name) { result = this.getFunction().getParameterByName(name) } - override predicate neverReturns() { - this.getFunction().neverReturns() - } + override predicate neverReturns() { this.getFunction().neverReturns() } override predicate functionAndOffset(CallableObjectInternal function, int offset) { function = this.getFunction() and offset = 1 @@ -501,10 +452,7 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { override predicate useOriginAsLegacyObject() { any() } - override predicate contextSensitiveCallee() { - this.getFunction().contextSensitiveCallee() - } + override predicate contextSensitiveCallee() { this.getFunction().contextSensitiveCallee() } override predicate isNotSubscriptedType() { any() } - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/objects/Classes.qll b/python/ql/src/semmle/python/objects/Classes.qll index 1e872e70c76..b509268a80a 100644 --- a/python/ql/src/semmle/python/objects/Classes.qll +++ b/python/ql/src/semmle/python/objects/Classes.qll @@ -1,6 +1,4 @@ import python - - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -10,19 +8,16 @@ private import semmle.python.types.Builtins /** Class representing classes */ abstract class ClassObjectInternal extends ObjectInternal { + override string getName() { result = this.getClassDeclaration().getName() } - override string getName() { - result = this.getClassDeclaration().getName() - } - - /** Holds if this is a class whose instances we treat specially, rather than as a generic instance. + /** + * Holds if this is a class whose instances we treat specially, rather than as a generic instance. * For example, `type` or `int`. */ - boolean isSpecial() { - result = Types::getMro(this).containsSpecial() - } + boolean isSpecial() { result = Types::getMro(this).containsSpecial() } - /** Looks up the attribute `name` on this class. + /** + * Looks up the attribute `name` on this class. * Note that this may be different from `this.attr(name)`. * For example given the class: * ```class C: @@ -51,11 +46,20 @@ abstract class ClassObjectInternal extends ObjectInternal { override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { instance = this and PointsToInternal::attributeRequired(this, name) and this.lookup(name, descriptor, _) and @@ -63,11 +67,14 @@ abstract class ClassObjectInternal extends ObjectInternal { } /** Approximation to descriptor protocol, skipping meta-descriptor protocol */ - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { exists(ObjectInternal descriptor, CfgOrigin desc_origin | - this.lookup(name, descriptor, desc_origin) | + this.lookup(name, descriptor, desc_origin) + | descriptor.isDescriptor() = false and - value = descriptor and origin = desc_origin + value = descriptor and + origin = desc_origin or descriptor.isDescriptor() = true and descriptor.descriptorGetClass(this, value, origin) @@ -80,13 +87,9 @@ abstract class ClassObjectInternal extends ObjectInternal { override boolean isClass() { result = true } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } override predicate subscriptUnknown() { none() } @@ -104,12 +107,10 @@ abstract class ClassObjectInternal extends ObjectInternal { } override predicate isNotSubscriptedType() { any() } - } /** Class representing Python source classes */ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject { - /** Gets the scope for this Python class */ Class getScope() { exists(ClassExpr expr | @@ -118,34 +119,24 @@ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject ) } - override string toString() { - result = "class " + this.getScope().getName() - } + override string toString() { result = "class " + this.getScope().getName() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TPythonClassObject(node) and context.appliesTo(node) } - override ClassDecl getClassDeclaration() { - this = TPythonClassObject(result) - } + override ClassDecl getClassDeclaration() { this = TPythonClassObject(result) } - override ObjectInternal getClass() { - result = Types::getMetaClass(this) - } + override ObjectInternal getClass() { result = Types::getMetaClass(this) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TPythonClassObject(result) - } + override ControlFlowNode getOrigin() { this = TPythonClassObject(result) } override predicate calleeAndOffset(Function scope, int paramOffset) { exists(PythonFunctionObjectInternal init | this.lookup("__init__", init, _) and - init.calleeAndOffset(scope, paramOffset-1) + init.calleeAndOffset(scope, paramOffset - 1) ) } @@ -153,7 +144,8 @@ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject Types::getMro(this).lookup(name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -169,27 +161,17 @@ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject override predicate functionAndOffset(CallableObjectInternal function, int offset) { this.lookup("__init__", function, _) and offset = 1 } - } /** Class representing built-in classes, except `type` */ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObject { + override Builtin getBuiltin() { this = TBuiltinClassObject(result) } - override Builtin getBuiltin() { - this = TBuiltinClassObject(result) - } + override string toString() { result = "builtin-class " + this.getBuiltin().getName() } - override string toString() { - result = "builtin-class " + this.getBuiltin().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } - - override ClassDecl getClassDeclaration() { - this = TBuiltinClassObject(result) - } + override ClassDecl getClassDeclaration() { this = TBuiltinClassObject(result) } override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) @@ -198,19 +180,16 @@ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObjec result = TType() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { Types::getMro(this).lookup(name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -222,33 +201,21 @@ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObjec } override predicate notTestableForEquality() { none() } - } /** A class representing an unknown class */ class UnknownClassInternal extends ClassObjectInternal, TUnknownClass { + override string toString() { result = "Unknown class" } - override string toString() { - result = "Unknown class" - } + override ClassDecl getClassDeclaration() { result = Builtin::unknownType() } - override ClassDecl getClassDeclaration() { - result = Builtin::unknownType() - } + override ObjectInternal getClass() { result = this } - override ObjectInternal getClass() { - result = this - } - - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } - override Builtin getBuiltin() { - result = Builtin::unknownType() - } + override Builtin getBuiltin() { result = Builtin::unknownType() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -258,134 +225,94 @@ class UnknownClassInternal extends ClassObjectInternal, TUnknownClass { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - none() - } - - pragma [noinline] override predicate attributesUnknown() { any() } + override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate attributesUnknown() { any() } } /** A class representing the built-in class `type`. */ class TypeInternal extends ClassObjectInternal, TType { + override string toString() { result = "builtin-class type" } - override string toString() { - result = "builtin-class type" - } + override ClassDecl getClassDeclaration() { result = Builtin::special("type") } - override ClassDecl getClassDeclaration() { - result = Builtin::special("type") - } + override ObjectInternal getClass() { result = this } - override ObjectInternal getClass() { - result = this - } - - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { none() } - override Builtin getBuiltin() { - result = Builtin::special("type") - } + override Builtin getBuiltin() { result = Builtin::special("type") } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { - none() - } + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { Types::getMro(this).lookup(name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { any() } - + pragma[noinline] + override predicate attributesUnknown() { any() } } /** A class representing a dynamically created class `type(name, *args, **kwargs)`. */ class DynamicallyCreatedClass extends ClassObjectInternal, TDynamicClass { + override string toString() { result = this.getOrigin().getNode().toString() } - override string toString() { - result = this.getOrigin().getNode().toString() - } - - override ObjectInternal getClass() { - this = TDynamicClass(_, result, _) - } + override ObjectInternal getClass() { this = TDynamicClass(_, result, _) } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { - none() - } + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - exists(ClassObjectInternal decl | - decl = Types::getMro(this).findDeclaringClass(name) | + exists(ClassObjectInternal decl | decl = Types::getMro(this).findDeclaringClass(name) | Types::declaredAttribute(decl, name, value, origin) ) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TDynamicClass(result, _, _) - } + override ControlFlowNode getOrigin() { this = TDynamicClass(result, _, _) } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TDynamicClass(node, _, context) } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate notTestableForEquality() { none() } override ClassDecl getClassDeclaration() { none() } - } class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { + ObjectInternal getGeneric() { this = TSubscriptedType(result, _) } - ObjectInternal getGeneric() { - this = TSubscriptedType(result, _) - } - - ObjectInternal getSpecializer() { - this = TSubscriptedType(_, result) - } + ObjectInternal getSpecializer() { this = TSubscriptedType(_, result) } override string getName() { result = this.getGeneric().getName() } - override string toString() { result = this.getGeneric().toString() + "[" + this.getSpecializer().toString() + "]" } + override string toString() { + result = this.getGeneric().toString() + "[" + this.getSpecializer().toString() + "]" + } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { exists(ObjectInternal generic, ObjectInternal index | @@ -395,16 +322,12 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { } /** Gets the class declaration for this object, if it is a class with a declaration. */ - override ClassDecl getClassDeclaration() { - result = this.getGeneric().getClassDeclaration() - } + override ClassDecl getClassDeclaration() { result = this.getGeneric().getClassDeclaration() } /** True if this "object" is a class. That is, its class inherits from `type` */ override boolean isClass() { result = true } - override ObjectInternal getClass() { - result = this.getGeneric().getClass() - } + override ObjectInternal getClass() { result = this.getGeneric().getClass() } override predicate notTestableForEquality() { none() } @@ -414,9 +337,11 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - override predicate calleeAndOffset(Function scope, int paramOffset){ none() } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } @@ -424,17 +349,25 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { override boolean isDescriptor() { result = false } - override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } override boolean booleanValue() { result = true } - override int intValue() { none()} + override int intValue() { none() } override string strValue() { none() } @@ -448,8 +381,4 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { none() } - } - - - diff --git a/python/ql/src/semmle/python/objects/Constants.qll b/python/ql/src/semmle/python/objects/Constants.qll index 1b93a3bb6f2..8cc0911af53 100644 --- a/python/ql/src/semmle/python/objects/Constants.qll +++ b/python/ql/src/semmle/python/objects/Constants.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -7,16 +6,13 @@ private import semmle.python.pointsto.MRO private import semmle.python.pointsto.PointsToContext private import semmle.python.types.Builtins - -/** Class representing constants. +/** + * Class representing constants. * Includes `None`, `True` and `False` as * well as strings and integers. */ abstract class ConstantObjectInternal extends ObjectInternal { - - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } @@ -32,33 +28,41 @@ abstract class ConstantObjectInternal extends ObjectInternal { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { PointsToInternal::attributeRequired(this, name) and exists(ObjectInternal cls_attr, CfgOrigin attr_orig | this.getClass().(ClassObjectInternal).lookup(name, cls_attr, attr_orig) and - cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin) + cls_attr.isDescriptor() = true and + cls_attr.descriptorGetInstance(this, value, origin) ) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(ClassObjectInternal cls | receiver_type(_, name, this, cls) and cls.lookup(name, descriptor, _) and @@ -77,29 +81,23 @@ abstract class ConstantObjectInternal extends ObjectInternal { abstract ImmutableLiteral getLiteral(); override predicate isNotSubscriptedType() { any() } - } pragma[nomagic] private boolean callToBool(CallNode call, PointsToContext context) { PointsToInternal::pointsTo(call.getFunction(), context, ClassValue::bool(), _) and exists(ObjectInternal arg | - PointsToInternal::pointsTo(call.getArg(0),context, arg, _) and + PointsToInternal::pointsTo(call.getArg(0), context, arg, _) and arg.booleanValue() = result ) } -private abstract class BooleanObjectInternal extends ConstantObjectInternal { - - override ObjectInternal getClass() { - result = ClassValue::bool() - } +abstract private class BooleanObjectInternal extends ConstantObjectInternal { + override ObjectInternal getClass() { result = ClassValue::bool() } override int length() { none() } - override string strValue() { - none() - } + override string strValue() { none() } /* Booleans aren't iterable */ override ObjectInternal getIterNext() { none() } @@ -107,18 +105,12 @@ private abstract class BooleanObjectInternal extends ConstantObjectInternal { override ImmutableLiteral getLiteral() { result.(BooleanLiteral).booleanValue() = this.booleanValue() } - } private class TrueObjectInternal extends BooleanObjectInternal, TTrue { + override string toString() { result = "bool True" } - override string toString() { - result = "bool True" - } - - override boolean booleanValue() { - result = true - } + override boolean booleanValue() { result = true } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { node.(NameNode).getId() = "True" and context.appliesTo(node) @@ -126,25 +118,15 @@ private class TrueObjectInternal extends BooleanObjectInternal, TTrue { callToBool(node, context) = true } - override int intValue() { - result = 1 - } - - override Builtin getBuiltin() { - result = Builtin::special("True") - } + override int intValue() { result = 1 } + override Builtin getBuiltin() { result = Builtin::special("True") } } private class FalseObjectInternal extends BooleanObjectInternal, TFalse { + override string toString() { result = "bool False" } - override string toString() { - result = "bool False" - } - - override boolean booleanValue() { - result = false - } + override boolean booleanValue() { result = false } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { node.(NameNode).getId() = "False" and context.appliesTo(node) @@ -152,84 +134,51 @@ private class FalseObjectInternal extends BooleanObjectInternal, TFalse { callToBool(node, context) = false } - override int intValue() { - result = 0 - } - - override Builtin getBuiltin() { - result = Builtin::special("False") - } + override int intValue() { result = 0 } + override Builtin getBuiltin() { result = Builtin::special("False") } } private class NoneObjectInternal extends ConstantObjectInternal, TNone { + override string toString() { result = "None" } - override string toString() { - result = "None" - } + override boolean booleanValue() { result = false } - override boolean booleanValue() { - result = false - } - - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("NoneType")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("NoneType")) } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { node.(NameNode).getId() = "None" and context.appliesTo(node) } - override Builtin getBuiltin() { - result = Builtin::special("None") - } + override Builtin getBuiltin() { result = Builtin::special("None") } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } override int length() { none() } /* None isn't iterable */ override ObjectInternal getIterNext() { none() } - override ImmutableLiteral getLiteral() { - result instanceof None - } - + override ImmutableLiteral getLiteral() { result instanceof None } } - class IntObjectInternal extends ConstantObjectInternal, TInt { - - override string toString() { - result = "int " + this.intValue().toString() - } + override string toString() { result = "int " + this.intValue().toString() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { context.appliesTo(node) and node.getNode().(IntegerLiteral).getValue() = this.intValue() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("int")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("int")) } - override Builtin getBuiltin() { - result.intValue() = this.intValue() - } + override Builtin getBuiltin() { result.intValue() = this.intValue() } - override int intValue() { - this = TInt(result) - } + override int intValue() { this = TInt(result) } - override string strValue() { - none() - } + override string strValue() { none() } override boolean booleanValue() { this.intValue() = 0 and result = false @@ -247,17 +196,13 @@ class IntObjectInternal extends ConstantObjectInternal, TInt { or result.(NegativeIntegerLiteral).getOperand().(IntegerLiteral).getValue() = -this.intValue() } - } class FloatObjectInternal extends ConstantObjectInternal, TFloat { - override string toString() { - if this.floatValue() = this.floatValue().floor() then ( - result = "float " + this.floatValue().floor().toString() + ".0" - ) else ( - result = "float " + this.floatValue().toString() - ) + if this.floatValue() = this.floatValue().floor() + then result = "float " + this.floatValue().floor().toString() + ".0" + else result = "float " + this.floatValue().toString() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { @@ -265,25 +210,15 @@ class FloatObjectInternal extends ConstantObjectInternal, TFloat { node.getNode().(FloatLiteral).getValue() = this.floatValue() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("float")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("float")) } - override Builtin getBuiltin() { - result.floatValue() = this.floatValue() - } + override Builtin getBuiltin() { result.floatValue() = this.floatValue() } - float floatValue() { - this = TFloat(result) - } + float floatValue() { this = TFloat(result) } - override int intValue() { - this = TFloat(result) - } + override int intValue() { this = TFloat(result) } - override string strValue() { - none() - } + override string strValue() { none() } override boolean booleanValue() { this.floatValue() = 0.0 and result = false @@ -296,18 +231,11 @@ class FloatObjectInternal extends ConstantObjectInternal, TFloat { /* floats aren't iterable */ override ObjectInternal getIterNext() { none() } - override ImmutableLiteral getLiteral() { - result.(FloatLiteral).getValue() = this.floatValue() - } - + override ImmutableLiteral getLiteral() { result.(FloatLiteral).getValue() = this.floatValue() } } - class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode { - - override string toString() { - result = "'" + this.strValue() + "'" - } + override string toString() { result = "'" + this.strValue() + "'" } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { context.appliesTo(node) and @@ -315,22 +243,16 @@ class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode { node.getNode().(StrConst).isUnicode() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("unicode")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("unicode")) } override Builtin getBuiltin() { result.(Builtin).strValue() = this.strValue() and result.getClass() = Builtin::special("unicode") } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - this = TUnicode(result) - } + override string strValue() { this = TUnicode(result) } override boolean booleanValue() { this.strValue() = "" and result = false @@ -338,25 +260,15 @@ class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode { this.strValue() != "" and result = true } - override int length() { - result = this.strValue().length() - } + override int length() { result = this.strValue().length() } - override ObjectInternal getIterNext() { - result = TUnknownInstance(this.getClass()) - } - - override ImmutableLiteral getLiteral() { - result.(Unicode).getText() = this.strValue() - } + override ObjectInternal getIterNext() { result = TUnknownInstance(this.getClass()) } + override ImmutableLiteral getLiteral() { result.(Unicode).getText() = this.strValue() } } class BytesObjectInternal extends ConstantObjectInternal, TBytes { - - override string toString() { - result = "'" + this.strValue() + "'" - } + override string toString() { result = "'" + this.strValue() + "'" } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { context.appliesTo(node) and @@ -364,22 +276,16 @@ class BytesObjectInternal extends ConstantObjectInternal, TBytes { not node.getNode().(StrConst).isUnicode() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("bytes")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("bytes")) } override Builtin getBuiltin() { result.(Builtin).strValue() = this.strValue() and result.getClass() = Builtin::special("bytes") } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - this = TBytes(result) - } + override string strValue() { this = TBytes(result) } override boolean booleanValue() { this.strValue() = "" and result = false @@ -387,20 +293,9 @@ class BytesObjectInternal extends ConstantObjectInternal, TBytes { this.strValue() != "" and result = true } - override int length() { - result = this.strValue().length() - } + override int length() { result = this.strValue().length() } - override ObjectInternal getIterNext() { - result = TUnknownInstance(this.getClass()) - } - - override ImmutableLiteral getLiteral() { - result.(Bytes).getText() = this.strValue() - } + override ObjectInternal getIterNext() { result = TUnknownInstance(this.getClass()) } + override ImmutableLiteral getLiteral() { result.(Bytes).getText() = this.strValue() } } - - - - diff --git a/python/ql/src/semmle/python/objects/Descriptors.qll b/python/ql/src/semmle/python/objects/Descriptors.qll index dbc3e59afa5..ece746d8625 100644 --- a/python/ql/src/semmle/python/objects/Descriptors.qll +++ b/python/ql/src/semmle/python/objects/Descriptors.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -9,16 +8,11 @@ private import semmle.python.types.Builtins /** Class representing property objects in Python */ class PropertyInternal extends ObjectInternal, TProperty { - /** Gets the name of this property */ - override string getName() { - result = this.getGetter().getName() - } + override string getName() { result = this.getGetter().getName() } /** Gets the getter function of this property */ - CallableObjectInternal getGetter() { - this = TProperty(_, _, result) - } + CallableObjectInternal getGetter() { this = TProperty(_, _, result) } private CallNode getCallNode() { this = TProperty(result, _, _) } @@ -55,11 +49,9 @@ class PropertyInternal extends ObjectInternal, TProperty { ) } - private Context getContext() { this = TProperty(_,result, _) } + private Context getContext() { this = TProperty(_, result, _) } - override string toString() { - result = "property " + this.getName() - } + override string toString() { result = "property " + this.getName() } override boolean booleanValue() { result = true } @@ -79,7 +71,9 @@ class PropertyInternal extends ObjectInternal, TProperty { override ControlFlowNode getOrigin() { this = TProperty(result, _, _) } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } @@ -89,7 +83,8 @@ class PropertyInternal extends ObjectInternal, TProperty { override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = TPropertySetterOrDeleter(this, name) and origin = CfgOrigin::unknown() } @@ -103,20 +98,28 @@ class PropertyInternal extends ObjectInternal, TProperty { override predicate binds(ObjectInternal cls, string name, ObjectInternal descriptor) { none() } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this and origin = CfgOrigin::fromCfgNode(this.getOrigin()) + value = this and + origin = CfgOrigin::fromCfgNode(this.getOrigin()) } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { - /* Just give an unknown value for now. We could improve this, but it would mean + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + /* + * Just give an unknown value for now. We could improve this, but it would mean * changing Contexts to account for property accesses. */ + exists(ClassObjectInternal cls, string name | name = this.getName() and receiver_type(_, name, instance, cls) and cls.lookup(name, this, _) and - origin = CfgOrigin::unknown() and value = ObjectInternal::unknown() + origin = CfgOrigin::unknown() and + value = ObjectInternal::unknown() ) } @@ -128,40 +131,31 @@ class PropertyInternal extends ObjectInternal, TProperty { override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } private class PropertySetterOrDeleter extends ObjectInternal, TPropertySetterOrDeleter { + override string toString() { result = this.getProperty().toString() + "." + this.getName() } - override string toString() { - result = this.getProperty().toString() + "." + this.getName() - } + override string getName() { this = TPropertySetterOrDeleter(_, result) } - override string getName() { - this = TPropertySetterOrDeleter(_, result) - } - - PropertyInternal getProperty() { - this = TPropertySetterOrDeleter(result, _) - } + PropertyInternal getProperty() { this = TPropertySetterOrDeleter(result, _) } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { exists(ControlFlowNode call | - obj = this.getProperty() and obj = TProperty(call, _, _) and + obj = this.getProperty() and + obj = TProperty(call, _, _) and origin = CfgOrigin::fromCfgNode(call) ) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("MethodType")) + result = TBuiltinClassObject(Builtin::special("MethodType")) } override predicate notTestableForEquality() { none() } @@ -170,7 +164,9 @@ private class PropertySetterOrDeleter extends ObjectInternal, TPropertySetterOrD override ControlFlowNode getOrigin() { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override int intValue() { none() } @@ -196,23 +192,24 @@ private class PropertySetterOrDeleter extends ObjectInternal, TPropertySetterOrD override ObjectInternal getIterNext() { none() } - override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } - /** A class representing classmethods in Python */ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { - - override string toString() { - result = "classmethod(" + this.getFunction() + ")" - } + override string toString() { result = "classmethod(" + this.getFunction() + ")" } override boolean booleanValue() { result = true } @@ -224,9 +221,7 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { } /** Gets the function wrapped by this classmethod object */ - CallableObjectInternal getFunction() { - this = TClassMethod(_, result) - } + CallableObjectInternal getFunction() { this = TClassMethod(_, result) } override ClassDecl getClassDeclaration() { none() } @@ -240,7 +235,9 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override ControlFlowNode getOrigin() { this = TClassMethod(result, _) } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } @@ -258,26 +255,31 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { value = TBoundMethod(cls, this.getFunction()) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { any(ObjectInternal obj).binds(instance, _, this) and value = TBoundMethod(instance.getClass(), this.getFunction()) and origin = CfgOrigin::unknown() } - /** Holds if attribute lookup on this object may "bind" `cls` to `descriptor`. + /** + * Holds if attribute lookup on this object may "bind" `cls` to `descriptor`. * `cls` will always be a class as this is a classmethod. * Here "bind" means that `instance` is passed to the `classmethod.__get__()` method * at runtime. The term "bind" is used as this most likely results in a bound-method. */ - pragma [noinline] override predicate binds(ObjectInternal cls, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal cls, string name, ObjectInternal descriptor) { descriptor = this.getFunction() and - exists(ObjectInternal instance | - any(ObjectInternal obj).binds(instance, name, this) | + exists(ObjectInternal instance | any(ObjectInternal obj).binds(instance, name, this) | instance.isClass() = false and cls = instance.getClass() or instance.isClass() = true and cls = instance @@ -286,9 +288,7 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override int length() { none() } - override string getName() { - result = this.getFunction().getName() - } + override string getName() { result = this.getFunction().getName() } override predicate contextSensitiveCallee() { none() } @@ -298,14 +298,10 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { - - override string toString() { - result = "staticmethod()" - } + override string toString() { result = "staticmethod()" } override boolean booleanValue() { result = true } @@ -316,9 +312,7 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { ) } - CallableObjectInternal getFunction() { - this = TStaticMethod(_, result) - } + CallableObjectInternal getFunction() { this = TStaticMethod(_, result) } override ClassDecl getClassDeclaration() { none() } @@ -332,7 +326,9 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { override ControlFlowNode getOrigin() { this = TStaticMethod(result, _) } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } @@ -352,23 +348,29 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this.getFunction() and origin = CfgOrigin::unknown() + value = this.getFunction() and + origin = CfgOrigin::unknown() } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { any(ObjectInternal obj).binds(instance, _, this) and - value = this.getFunction() and origin = CfgOrigin::unknown() + value = this.getFunction() and + origin = CfgOrigin::unknown() } - override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } - override string getName() { - result = this.getFunction().getName() - } + override string getName() { result = this.getFunction().getName() } override predicate contextSensitiveCallee() { none() } @@ -378,5 +380,4 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } diff --git a/python/ql/src/semmle/python/objects/Instances.qll b/python/ql/src/semmle/python/objects/Instances.qll index ab5a12b5070..396e26d8aad 100644 --- a/python/ql/src/semmle/python/objects/Instances.qll +++ b/python/ql/src/semmle/python/objects/Instances.qll @@ -1,6 +1,4 @@ import python - - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -10,18 +8,19 @@ private import semmle.python.types.Builtins /** A class representing instances */ abstract class InstanceObject extends ObjectInternal { - - pragma [nomagic] + pragma[nomagic] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - exists(ObjectInternal cls_attr | - this.classAttribute(name, cls_attr) - | - /* If class attribute is not a descriptor, that usually means it is some sort of + exists(ObjectInternal cls_attr | this.classAttribute(name, cls_attr) | + /* + * If class attribute is not a descriptor, that usually means it is some sort of * default value and likely overridden by an instance attribute. In that case * use `unknown` to signal that an attribute exists but to avoid false positives * f using the default value. */ - cls_attr.isDescriptor() = false and value = ObjectInternal::unknown() and origin = CfgOrigin::unknown() + + cls_attr.isDescriptor() = false and + value = ObjectInternal::unknown() and + origin = CfgOrigin::unknown() or cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin) ) @@ -29,13 +28,13 @@ abstract class InstanceObject extends ObjectInternal { this.selfAttribute(name, value, origin) } - pragma [noinline] + pragma[noinline] private predicate classAttribute(string name, ObjectInternal cls_attr) { PointsToInternal::attributeRequired(this, name) and this.getClass().(ClassObjectInternal).lookup(name, cls_attr, _) } - pragma [noinline] + pragma[noinline] private predicate selfAttribute(string name, ObjectInternal value, CfgOrigin origin) { PointsToInternal::attributeRequired(this, name) and exists(EssaVariable self, PythonFunctionObjectInternal init, Context callee | @@ -56,7 +55,6 @@ abstract class InstanceObject extends ObjectInternal { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } private predicate self_variable_reaching_init_exit(EssaVariable self) { @@ -65,14 +63,12 @@ private predicate self_variable_reaching_init_exit(EssaVariable self) { self.getScope().getName() = "__init__" } -/** A class representing instances instantiated at a specific point in the program (statically) +/** + * A class representing instances instantiated at a specific point in the program (statically) * For example the code `C()` would be a specific instance of `C`. */ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { - - override string toString() { - result = this.getOrigin().getNode().toString() - } + override string toString() { result = this.getOrigin().getNode().toString() } override boolean booleanValue() { //result = this.getClass().instancesBooleanValue() @@ -84,9 +80,7 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { } /** Gets the class declaration for this object, if it is a declared class. */ - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } @@ -95,64 +89,65 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { override ObjectInternal getClass() { exists(ClassObjectInternal cls, ClassDecl decl | this = TSpecificInstance(_, cls, _) and - decl = cls.getClassDeclaration() | - if decl.callReturnsInstance() then - result = cls - else - result = TUnknownClass() + decl = cls.getClassDeclaration() + | + if decl.callReturnsInstance() then result = cls else result = TUnknownClass() ) } - /** Gets the `Builtin` for this object, if any. - * All objects (except unknown and undefined values) should return + /** + * Gets the `Builtin` for this object, if any. + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getOrigin()`. */ - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * objects. - * All objects (except unknown and undefined values) should return + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getBuiltin()`. */ - override ControlFlowNode getOrigin() { - this = TSpecificInstance(result, _, _) - } + override ControlFlowNode getOrigin() { this = TSpecificInstance(result, _, _) } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { // TO DO -- Handle cases where class overrides __call__ in more detail, like normal calls. this.getClass().(ClassObjectInternal).lookup("__call__", _, _) and - obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() + obj = ObjectInternal::unknown() and + origin = CfgOrigin::unknown() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(ClassObjectInternal cls | receiver_type(_, name, this, cls) and cls.lookup(name, descriptor, _) and @@ -161,9 +156,7 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { this = instance } - override int length() { - result = lengthFromClass(this.getClass()) - } + override int length() { result = lengthFromClass(this.getClass()) } override predicate initializer(PythonFunctionObjectInternal init, Context callee) { exists(CallNode call, Context caller, ClassObjectInternal cls | @@ -174,13 +167,12 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { } override predicate useOriginAsLegacyObject() { none() } - } -/** A class representing context-free instances represented by `self` in the source code +/** + * A class representing context-free instances represented by `self` in the source code */ class SelfInstanceInternal extends TSelfInstance, InstanceObject { - override string toString() { result = "self instance of " + this.getClass().(ClassObjectInternal).getName() } @@ -191,34 +183,24 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { result = maybe() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } predicate parameterAndContext(ParameterDefinition def, PointsToContext context) { this = TSelfInstance(def, context, _) } /** Gets the class declaration for this object, if it is a declared class. */ - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override predicate notTestableForEquality() { any() } - override ObjectInternal getClass() { - this = TSelfInstance(_, _, result) - } + override ObjectInternal getClass() { this = TSelfInstance(_, _, result) } - ParameterDefinition getParameter() { - this = TSelfInstance(result, _, _) - } + ParameterDefinition getParameter() { this = TSelfInstance(result, _, _) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override ControlFlowNode getOrigin() { exists(ParameterDefinition def | @@ -231,35 +213,39 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { // In general instances aren't callable, but some are... // TO DO -- Handle cases where class overrides __call__ none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(AttrNode attr, ClassObjectInternal cls | receiver_type(attr, name, this, cls) and cls_descriptor(cls, name, descriptor) @@ -267,9 +253,7 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { instance = this } - override int length() { - result = lengthFromClass(this.getClass()) - } + override int length() { result = lengthFromClass(this.getClass()) } override predicate initializer(PythonFunctionObjectInternal init, Context callee) { callee.isRuntime() and @@ -278,53 +262,41 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { } override predicate useOriginAsLegacyObject() { none() } - } /** A class representing a value that has a known class, but no other information */ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { - override string toString() { result = "instance of " + this.getClass().(ClassObjectInternal).getName() } - override boolean booleanValue() { - result = maybe() - } + override boolean booleanValue() { result = maybe() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } /** Gets the class declaration for this object, if it is a declared class. */ - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override predicate notTestableForEquality() { any() } - override ObjectInternal getClass() { - this = TUnknownInstance(result) - } + override ObjectInternal getClass() { this = TUnknownInstance(result) } - /** Gets the `Builtin` for this object, if any. - * All objects (except unknown and undefined values) should return + /** + * Gets the `Builtin` for this object, if any. + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getOrigin()`. */ - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * objects. - * All objects (except unknown and undefined values) should return + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getBuiltin()`. */ - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -336,40 +308,45 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { PointsToInternal::attributeRequired(this, name) and exists(ObjectInternal cls_attr, CfgOrigin attr_orig | this.getClass().(ClassObjectInternal).lookup(name, cls_attr, attr_orig) - | + | cls_attr.isDescriptor() = false and value = cls_attr and origin = attr_orig or cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin) ) } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(AttrNode attr, ClassObjectInternal cls | receiver_type(attr, name, this, cls) and cls_descriptor(cls, name, descriptor) @@ -377,9 +354,7 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { instance = this } - override int length() { - result = lengthFromClass(this.getClass()) - } + override int length() { result = lengthFromClass(this.getClass()) } override string getName() { none() } @@ -390,7 +365,6 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } private int lengthFromClass(ClassObjectInternal cls) { @@ -404,7 +378,6 @@ private predicate cls_descriptor(ClassObjectInternal cls, string name, ObjectInt /** A class representing an instance of the `super` class */ class SuperInstance extends TSuperInstance, ObjectInternal { - override string toString() { result = "super(" + this.getStartClass().toString() + ", " + this.getSelf().toString() + ")" } @@ -419,34 +392,28 @@ class SuperInstance extends TSuperInstance, ObjectInternal { } /** Gets the class declared as the starting point for MRO lookup. */ - ClassObjectInternal getStartClass() { - this = TSuperInstance(_, result) - } + ClassObjectInternal getStartClass() { this = TSuperInstance(_, result) } /** Gets 'self' object */ - ObjectInternal getSelf() { - this = TSuperInstance(result, _) - } + ObjectInternal getSelf() { this = TSuperInstance(result, _) } override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } - override ObjectInternal getClass() { - result = ObjectInternal::superType() - } + override ObjectInternal getClass() { result = ObjectInternal::superType() } override predicate notTestableForEquality() { any() } override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override int intValue() { none() } @@ -454,46 +421,60 @@ class SuperInstance extends TSuperInstance, ObjectInternal { override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { exists(ObjectInternal cls_attr, CfgOrigin attr_orig | this.attribute_descriptor(name, cls_attr, attr_orig) - | + | cls_attr.isDescriptor() = false and value = cls_attr and origin = attr_orig or - cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this.getSelf(), value, origin) + cls_attr.isDescriptor() = true and + cls_attr.descriptorGetInstance(this.getSelf(), value, origin) ) } /* Helper for `attribute` */ - pragma [noinline] private predicate attribute_descriptor(string name, ObjectInternal cls_attr, CfgOrigin attr_orig) { + pragma[noinline] + private predicate attribute_descriptor(string name, ObjectInternal cls_attr, CfgOrigin attr_orig) { PointsToInternal::attributeRequired(this, name) and this.lookup(name, cls_attr, attr_orig) } private predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - Types::getMro(this.getSelf().getClass()).startingAt(this.getStartClass()).getTail().lookup(name, value, origin) + Types::getMro(this.getSelf().getClass()) + .startingAt(this.getStartClass()) + .getTail() + .lookup(name, value, origin) } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { descriptor.isDescriptor() = true and this.lookup(name, descriptor, _) and instance = this.getSelf() and receiver_type(_, name, this, _) } - override int length() { - none() - } + override int length() { none() } override string getName() { none() } @@ -504,6 +485,4 @@ class SuperInstance extends TSuperInstance, ObjectInternal { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } - diff --git a/python/ql/src/semmle/python/objects/Modules.qll b/python/ql/src/semmle/python/objects/Modules.qll index fdc748ae0e9..83b8fb5769c 100644 --- a/python/ql/src/semmle/python/objects/Modules.qll +++ b/python/ql/src/semmle/python/objects/Modules.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -9,7 +8,6 @@ private import semmle.python.types.Builtins /** A class representing modules */ abstract class ModuleObjectInternal extends ObjectInternal { - /** Gets the source scope of this module, if it has one. */ abstract Module getSourceModule(); @@ -27,30 +25,35 @@ abstract class ModuleObjectInternal extends ObjectInternal { override predicate notTestableForEquality() { none() } - override boolean booleanValue() { - result = true - } + override boolean booleanValue() { result = true } - override ObjectInternal getClass() { - result = ObjectInternal::moduleType() - } + override ObjectInternal getClass() { result = ObjectInternal::moduleType() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } override predicate subscriptUnknown() { any() } /** Holds if this module is a `__init__.py` module. */ - predicate isInitModule() { - any(PackageObjectInternal package).getInitModule() = this - } + predicate isInitModule() { any(PackageObjectInternal package).getInitModule() = this } override predicate contextSensitiveCallee() { none() } @@ -59,14 +62,16 @@ abstract class ModuleObjectInternal extends ObjectInternal { /* Modules aren't iterable */ override ObjectInternal getIterNext() { none() } - /** Holds if this module "exports" name. + /** + * Holds if this module "exports" name. * That is, does it define `name` in `__all__` or is * `__all__` not defined and `name` a global variable that does not start with "_" * This is the set of names imported by `from ... import *`. */ predicate exports(string name) { - not this.(ModuleObjectInternal).attribute("__all__", _, _) and this.hasAttribute(name) - and not name.charAt(0) = "_" + not this.(ModuleObjectInternal).attribute("__all__", _, _) and + this.hasAttribute(name) and + not name.charAt(0) = "_" or py_exports(this.getSourceModule(), name) } @@ -75,101 +80,61 @@ abstract class ModuleObjectInternal extends ObjectInternal { abstract predicate hasCompleteExportInfo(); override predicate isNotSubscriptedType() { any() } - } /** A class representing built-in modules */ class BuiltinModuleObjectInternal extends ModuleObjectInternal, TBuiltinModuleObject { + override Builtin getBuiltin() { this = TBuiltinModuleObject(result) } - override Builtin getBuiltin() { - this = TBuiltinModuleObject(result) - } + override string toString() { result = "Module " + this.getBuiltin().getName() } - override string toString() { - result = "Module " + this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } - override string getName() { - result = this.getBuiltin().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override ClassDecl getClassDeclaration() { none() } - override ClassDecl getClassDeclaration() { - none() - } + override Module getSourceModule() { none() } - override Module getSourceModule() { - none() - } + override int intValue() { none() } - override int intValue() { - none() - } + override string strValue() { none() } - override string strValue() { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } - - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = ObjectInternal::fromBuiltin(this.getBuiltin().getMember(name)) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override ControlFlowNode getOrigin() { - none() - } - - override predicate hasCompleteExportInfo() { - any() - } + override ControlFlowNode getOrigin() { none() } + override predicate hasCompleteExportInfo() { any() } } /** A class representing packages */ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } - - override string toString() { - result = "Package " + this.getName() - } + override string toString() { result = "Package " + this.getName() } /** Gets the folder for this package */ - Folder getFolder() { - this = TPackageObject(result) - } + Folder getFolder() { this = TPackageObject(result) } - override string getName() { - result = moduleNameFromFile(this.getFolder()) - } + override string getName() { result = moduleNameFromFile(this.getFolder()) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } - override Module getSourceModule() { - result.getFile() = this.getFolder().getFile("__init__.py") - } + override Module getSourceModule() { result.getFile() = this.getFolder().getFile("__init__.py") } /** Gets the init module of this package */ - PythonModuleObjectInternal getInitModule() { - result = TPythonModule(this.getSourceModule()) - } + PythonModuleObjectInternal getInitModule() { result = TPythonModule(this.getSourceModule()) } predicate hasNoInitModule() { exists(Folder f | @@ -188,19 +153,14 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { ) } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { this.getInitModule().attribute(name, value, origin) or exists(Module init | @@ -215,12 +175,14 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { this.hasNoInitModule() and exists(ModuleObjectInternal mod | mod = this.submodule(name) and - value = mod | + value = mod + | origin = CfgOrigin::fromObject(mod) ) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override ControlFlowNode getOrigin() { exists(Module package | @@ -238,7 +200,6 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { } override predicate hasCompleteExportInfo() { - not exists(this.getInitModule()) or this.getInitModule().hasCompleteExportInfo() @@ -247,53 +208,34 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { /** A class representing Python modules */ class PythonModuleObjectInternal extends ModuleObjectInternal, TPythonModule { + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } + override string toString() { result = this.getSourceModule().toString() } - override string toString() { - result = this.getSourceModule().toString() - } + override string getName() { result = this.getSourceModule().getName() } - override string getName() { - result = this.getSourceModule().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override ClassDecl getClassDeclaration() { none() } - override ClassDecl getClassDeclaration() { - none() - } + override Module getSourceModule() { this = TPythonModule(result) } - override Module getSourceModule() { - this = TPythonModule(result) - } + override int intValue() { none() } - override int intValue() { - none() - } + override string strValue() { none() } - override string strValue() { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } - - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value != ObjectInternal::undefined() and ModuleAttributes::pointsToAtExit(this.getSourceModule(), name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override ControlFlowNode getOrigin() { - result = this.getSourceModule().getEntryNode() - } + override ControlFlowNode getOrigin() { result = this.getSourceModule().getEntryNode() } /** Holds if this value has the attribute `name` */ override predicate hasAttribute(string name) { @@ -317,76 +259,56 @@ class PythonModuleObjectInternal extends ModuleObjectInternal, TPythonModule { not exists(Call modify, Attribute attr, GlobalVariable all | modify.getScope() = this.getSourceModule() and modify.getFunc() = attr and - all.getId() = "__all__" | + all.getId() = "__all__" + | attr.getObject().(Name).uses(all) ) } - } /** A class representing a module that is missing from the DB, but inferred to exists from imports. */ class AbsentModuleObjectInternal extends ModuleObjectInternal, TAbsentModule { - - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override string toString() { - if exists(Module m, SyntaxError se | se.getFile() = m.getFile() and m.getName() = this.getName()) then - result = "Unparsable module " + this.getName() - else - result = "Missing module " + this.getName() + if + exists(Module m, SyntaxError se | se.getFile() = m.getFile() and m.getName() = this.getName()) + then result = "Unparsable module " + this.getName() + else result = "Missing module " + this.getName() } - override string getName() { - this = TAbsentModule(result) - } + override string getName() { this = TAbsentModule(result) } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { missing_imported_module(node, context, this.getName()) } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } - override Module getSourceModule() { - none() - } + override Module getSourceModule() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = TAbsentModuleAttribute(this, name) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate hasCompleteExportInfo() { - none() - } + override predicate hasCompleteExportInfo() { none() } } /** A class representing an attribute of a missing module. */ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleAttribute { - - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override string toString() { exists(ModuleObjectInternal mod, string name | @@ -396,39 +318,28 @@ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleA } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - exists(ModuleObjectInternal mod, string name | - this = TAbsentModuleAttribute(mod, name) | + exists(ModuleObjectInternal mod, string name | this = TAbsentModuleAttribute(mod, name) | PointsToInternal::pointsTo(node.(AttrNode).getObject(name), context, mod, _) or PointsToInternal::pointsTo(node.(ImportMemberNode).getModule(name), context, mod, _) ) } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() @@ -442,31 +353,36 @@ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleA override predicate notTestableForEquality() { any() } - override boolean booleanValue() { - result = maybe() - } + override boolean booleanValue() { result = maybe() } - override ObjectInternal getClass() { - result = ObjectInternal::unknownClass() - } + override ObjectInternal getClass() { result = ObjectInternal::unknownClass() } override boolean isDescriptor() { result = false } - override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } override predicate subscriptUnknown() { any() } - /* We know what this is called, but not its innate name. - * However, if we are looking for things by name, this is a reasonable approximation */ - override string getName() { - this = TAbsentModuleAttribute(_, result) - } + /* + * We know what this is called, but not its innate name. + * However, if we are looking for things by name, this is a reasonable approximation + */ + + override string getName() { this = TAbsentModuleAttribute(_, result) } override predicate contextSensitiveCallee() { none() } @@ -476,5 +392,4 @@ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleA override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 498856ae668..9d9d7cb0bbc 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -3,9 +3,6 @@ * A `Value` is a static approximation to a set of runtime objects. */ - - - import python private import TObject private import semmle.python.objects.ObjectInternal @@ -14,54 +11,48 @@ private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins -/* Use the term `ObjectSource` to refer to DB entity. Either a CFG node +/* + * Use the term `ObjectSource` to refer to DB entity. Either a CFG node * for Python objects, or `@py_cobject` entity for built-in objects. */ + class ObjectSource = Object; /* Aliases for scopes */ class FunctionScope = Function; + class ClassScope = Class; + class ModuleScope = Module; -/** Class representing values in the Python program +/** + * Class representing values in the Python program * Each `Value` is a static approximation to a set of one or more real objects. */ class Value extends TObject { - Value() { this != ObjectInternal::unknown() and this != ObjectInternal::unknownClass() and this != ObjectInternal::undefined() } - string toString() { - result = this.(ObjectInternal).toString() - } + string toString() { result = this.(ObjectInternal).toString() } /** Gets a `ControlFlowNode` that refers to this object. */ - ControlFlowNode getAReference() { - PointsToInternal::pointsTo(result, _, this, _) - } + ControlFlowNode getAReference() { PointsToInternal::pointsTo(result, _, this, _) } /** Gets the origin CFG node for this value. */ - ControlFlowNode getOrigin() { - result = this.(ObjectInternal).getOrigin() - } + ControlFlowNode getOrigin() { result = this.(ObjectInternal).getOrigin() } - - /** Gets the class of this object. + /** + * Gets the class of this object. * Strictly, the `Value` representing the class of the objects * represented by this Value. */ - ClassValue getClass() { - result = this.(ObjectInternal).getClass() - } + ClassValue getClass() { result = this.(ObjectInternal).getClass() } /** Gets a call to this object */ - CallNode getACall() { - result = this.getACall(_) - } + CallNode getACall() { result = this.getACall(_) } /** Gets a call to this object with the given `caller` context. */ CallNode getACall(PointsToContext caller) { @@ -74,36 +65,34 @@ class Value extends TObject { } /** Gets a `Value` that represents the attribute `name` of this object. */ - Value attr(string name) { - this.(ObjectInternal).attribute(name, result, _) - } + Value attr(string name) { this.(ObjectInternal).attribute(name, result, _) } - /** Holds if this value is builtin. Applies to built-in functions and methods, + /** + * Holds if this value is builtin. Applies to built-in functions and methods, * but also integers and strings. */ - predicate isBuiltin() { - this.(ObjectInternal).isBuiltin() - } + predicate isBuiltin() { this.(ObjectInternal).isBuiltin() } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.(ObjectInternal).getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec) or not exists(this.(ObjectInternal).getOrigin()) and - filepath = "" and bl = 0 and bc = 0 and el = 0 and ec = 0 + filepath = "" and + bl = 0 and + bc = 0 and + el = 0 and + ec = 0 } - /** Gets the name of this value, if it has one. + /** + * Gets the name of this value, if it has one. * Note this is the innate name of the * object, not necessarily all the names by which it can be called. */ - final string getName() { - result = this.(ObjectInternal).getName() - } + final string getName() { result = this.(ObjectInternal).getName() } /** Holds if this value has the attribute `name` */ - predicate hasAttribute(string name) { - this.(ObjectInternal).hasAttribute(name) - } + predicate hasAttribute(string name) { this.(ObjectInternal).hasAttribute(name) } /** Whether this value is absent from the database, but has been inferred to likely exist */ predicate isAbsent() { @@ -112,7 +101,8 @@ class Value extends TObject { this instanceof AbsentModuleAttributeObjectInternal } - /** Whether this overrides v. In this context, "overrides" means that this object + /** + * Whether this overrides v. In this context, "overrides" means that this object * is a named attribute of a some class C and `v` is a named attribute of another * class S, both attributes having the same name, and S is a super class of C. */ @@ -124,46 +114,42 @@ class Value extends TObject { ) } - /** Gets the boolean interpretation of this value. - * Could be both `true` and `false`, if we can't determine the result more precisely. - */ - boolean getABooleanValue() { - result = this.(ObjectInternal).booleanValue() - } + /** + * Gets the boolean interpretation of this value. + * Could be both `true` and `false`, if we can't determine the result more precisely. + */ + boolean getABooleanValue() { result = this.(ObjectInternal).booleanValue() } - /** Gets the boolean interpretation of this value, only if we can determine the result precisely. - * The result can be `none()`, but never both `true` and `false`. - */ + /** + * Gets the boolean interpretation of this value, only if we can determine the result precisely. + * The result can be `none()`, but never both `true` and `false`. + */ boolean getDefiniteBooleanValue() { result = getABooleanValue() and not (getABooleanValue() = true and getABooleanValue() = false) } } -/** Class representing modules in the Python program +/** + * Class representing modules in the Python program * Each `ModuleValue` represents a module object in the Python program. */ class ModuleValue extends Value { + ModuleValue() { this instanceof ModuleObjectInternal } - ModuleValue() { - this instanceof ModuleObjectInternal - } - - /** Holds if this module "exports" name. + /** + * Holds if this module "exports" name. * That is, does it define `name` in `__all__` or is * `__all__` not defined and `name` a global variable that does not start with "_" * This is the set of names imported by `from ... import *`. */ - predicate exports(string name) { - PointsTo::moduleExports(this, name) - } + predicate exports(string name) { PointsTo::moduleExports(this, name) } /** Gets the scope for this module, provided that it is a Python module. */ - ModuleScope getScope() { - result = this.(ModuleObjectInternal).getSourceModule() - } + ModuleScope getScope() { result = this.(ModuleObjectInternal).getSourceModule() } - /** Gets the container path for this module. Will be the file for a Python module, + /** + * Gets the container path for this module. Will be the file for a Python module, * the folder for a package and no result for a builtin module. */ Container getPath() { @@ -172,26 +158,20 @@ class ModuleValue extends Value { result = this.(PythonModuleObjectInternal).getSourceModule().getFile() } - /** Whether this module is imported by 'import name'. For example on a linux system, - * the module 'posixpath' is imported as 'os.path' or as 'posixpath' */ - predicate importedAs(string name) { - PointsToInternal::module_imported_as(this, name) - } + /** + * Whether this module is imported by 'import name'. For example on a linux system, + * the module 'posixpath' is imported as 'os.path' or as 'posixpath' + */ + predicate importedAs(string name) { PointsToInternal::module_imported_as(this, name) } /** Whether this module is a package. */ - predicate isPackage() { - this instanceof PackageObjectInternal - } + predicate isPackage() { this instanceof PackageObjectInternal } /** Whether the complete set of names "exported" by this module can be accurately determined */ - predicate hasCompleteExportInfo() { - this.(ModuleObjectInternal).hasCompleteExportInfo() - } + predicate hasCompleteExportInfo() { this.(ModuleObjectInternal).hasCompleteExportInfo() } /** Get a module that this module imports */ - ModuleValue getAnImportedModule() { - result.importedAs(this.getScope().getAnImportedModuleName()) - } + ModuleValue getAnImportedModule() { result.importedAs(this.getScope().getAnImportedModuleName()) } /** When used as a normal module (for example, imported and used by other modules) */ predicate isUsedAsModule() { @@ -214,7 +194,8 @@ class ModuleValue extends Value { i.getScope() = this.getScope() and op instanceof Eq and i.getTest().(Compare).compares(name, op, main) and - name.getId() = "__name__" and main.getText() = "__main__" + name.getId() = "__name__" and + main.getText() = "__main__" ) or exists(Comment c | @@ -227,8 +208,8 @@ class ModuleValue extends Value { } module Module { - - /** Gets the `ModuleValue` named `name`. + /** + * Gets the `ModuleValue` named `name`. * * Note that the name used to refer to a module is not * necessarily its name. For example, @@ -245,25 +226,23 @@ module Module { /* Prevent runaway recursion when a module has itself as an attribute. */ private ModuleValue named(string name, int dots) { - dots = 0 and not name.charAt(_) = "." and + dots = 0 and + not name.charAt(_) = "." and result.getName() = name or dots <= 3 and - exists(string modname, string attrname | - name = modname + "." + attrname | - result = named(modname, dots-1).attr(attrname) + exists(string modname, string attrname | name = modname + "." + attrname | + result = named(modname, dots - 1).attr(attrname) ) } /** Get the `ModuleValue` for the `builtin` module. */ - ModuleValue builtinModule() { - result = TBuiltinModuleObject(Builtin::builtinModule()) - } + ModuleValue builtinModule() { result = TBuiltinModuleObject(Builtin::builtinModule()) } } module Value { - - /** Gets the `Value` named `name`. + /** + * Gets the `Value` named `name`. * If there is at least one '.' in `name`, then the part of * the name to the left of the rightmost '.' is interpreted as a module name * and the part after the rightmost '.' as an attribute of that module. @@ -274,8 +253,7 @@ module Value { * For example `Value::named("len")` is the `Value` representing the `len` built-in function. */ Value named(string name) { - exists(string modname, string attrname | - name = modname + "." + attrname | + exists(string modname, string attrname | name = modname + "." + attrname | result = Module::named(modname).attr(attrname) ) or @@ -288,34 +266,32 @@ module Value { name = "False" and result = TFalse() } - /** Gets the `NumericValue` for the integer constant `i`, if it exists. + /** + * Gets the `NumericValue` for the integer constant `i`, if it exists. * There will be no `NumericValue` for most integers, but the following are * guaranteed to exist: * * From zero to 511 inclusive. * * All powers of 2 (up to 2**30) * * Any integer explicitly mentioned in the source program. */ - NumericValue forInt(int i) { - result.(IntObjectInternal).intValue() = i - } + NumericValue forInt(int i) { result.(IntObjectInternal).intValue() = i } - /** Gets the `Value` for the bytes constant `bytes`, if it exists. + /** + * Gets the `Value` for the bytes constant `bytes`, if it exists. * There will be no `Value` for most byte strings, unless it is explicitly * declared in the source program. */ - StringValue forBytes(string bytes) { - result.(BytesObjectInternal).strValue() = bytes - } + StringValue forBytes(string bytes) { result.(BytesObjectInternal).strValue() = bytes } - /** Gets the `Value` for the unicode constant `text`, if it exists. + /** + * Gets the `Value` for the unicode constant `text`, if it exists. * There will be no `Value` for most text strings, unless it is explicitly * declared in the source program. */ - StringValue forUnicode(string text) { - result.(UnicodeObjectInternal).strValue() = text - } + StringValue forUnicode(string text) { result.(UnicodeObjectInternal).strValue() = text } - /** Gets a `Value` for the string `text`. May be a bytes or unicode string for Python 2. + /** + * Gets a `Value` for the string `text`. May be a bytes or unicode string for Python 2. * There will be no `Value` for most strings, unless it is explicitly * declared in the source program. */ @@ -334,9 +310,7 @@ module Value { } /** Gets the `Value` for `None`. */ - Value none_() { - result = ObjectInternal::none_() - } + Value none_() { result = ObjectInternal::none_() } /** * Shorcuts added by the `site` module to exit your interactive session. @@ -353,32 +327,25 @@ module Value { } } -/** Class representing callables in the Python program +/** + * Class representing callables in the Python program * Callables include Python functions, built-in functions and bound-methods, * but not classes. */ class CallableValue extends Value { + CallableValue() { this instanceof CallableObjectInternal } - CallableValue() { - this instanceof CallableObjectInternal - } - - /** Holds if this callable never returns once called. + /** + * Holds if this callable never returns once called. * For example, `sys.exit` */ - predicate neverReturns() { - this.(CallableObjectInternal).neverReturns() - } + predicate neverReturns() { this.(CallableObjectInternal).neverReturns() } /** Gets the scope for this function, provided that it is a Python function. */ - FunctionScope getScope() { - result = this.(PythonFunctionObjectInternal).getScope() - } + FunctionScope getScope() { result = this.(PythonFunctionObjectInternal).getScope() } /** Gets the `n`th parameter node of this callable. */ - NameNode getParameter(int n) { - result = this.(CallableObjectInternal).getParameter(n) - } + NameNode getParameter(int n) { result = this.(CallableObjectInternal).getParameter(n) } /** Gets the `name`d parameter node of this callable. */ NameNode getParameterByName(string name) { @@ -386,56 +353,60 @@ class CallableValue extends Value { } /** Gets the argument corresponding to the `n'th parameter node of this callable. */ - cached ControlFlowNode getArgumentForCall(CallNode call, int n) { + cached + ControlFlowNode getArgumentForCall(CallNode call, int n) { exists(ObjectInternal called, int offset | PointsToInternal::pointsTo(call.getFunction(), _, called, _) and called.functionAndOffset(this, offset) - | - call.getArg(n-offset) = result + | + call.getArg(n - offset) = result or - exists(string name | call.getArgByName(name) = result and this.(PythonFunctionObjectInternal).getScope().getArg(n+offset).getName() = name) + exists(string name | + call.getArgByName(name) = result and + this.(PythonFunctionObjectInternal).getScope().getArg(n + offset).getName() = name + ) or called instanceof BoundMethodObjectInternal and - offset = 1 and n = 0 and result = call.getFunction().(AttrNode).getObject() + offset = 1 and + n = 0 and + result = call.getFunction().(AttrNode).getObject() ) } - /** Gets the argument corresponding to the `name`d parameter node of this callable. */ - cached ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { + cached + ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { exists(CallableObjectInternal called, int offset | PointsToInternal::pointsTo(call.getFunction(), _, called, _) and called.functionAndOffset(this, offset) - | + | exists(int n | call.getArg(n) = result and - this.(PythonFunctionObjectInternal).getScope().getArg(n+offset).getName() = name + this.(PythonFunctionObjectInternal).getScope().getArg(n + offset).getName() = name ) or call.getArgByName(name) = result and exists(this.(PythonFunctionObjectInternal).getScope().getArgByName(name)) or called instanceof BoundMethodObjectInternal and - offset = 1 and name = "self" and result = call.getFunction().(AttrNode).getObject() + offset = 1 and + name = "self" and + result = call.getFunction().(AttrNode).getObject() ) } - } -/** Class representing classes in the Python program, both Python and built-in. +/** + * Class representing classes in the Python program, both Python and built-in. */ class ClassValue extends Value { - - ClassValue() { - this.(ObjectInternal).isClass() = true - } + ClassValue() { this.(ObjectInternal).isClass() = true } /** Gets an improper super type of this class. */ - ClassValue getASuperType() { - result = this.getABaseType*() - } + ClassValue getASuperType() { result = this.getABaseType*() } - /** Looks up the attribute `name` on this class. + /** + * Looks up the attribute `name` on this class. * Note that this may be different from `this.attr(name)`. * For example given the class: * ```class C: @@ -446,13 +417,9 @@ class ClassValue extends Value { * whereas * `this.attr("f") is equivalent to `C.f`, which is a bound-method. */ - Value lookup(string name) { - this.(ClassObjectInternal).lookup(name, result, _) - } + Value lookup(string name) { this.(ClassObjectInternal).lookup(name, result, _) } - predicate isCallable() { - this.(ClassObjectInternal).lookup("__call__", _, _) - } + predicate isCallable() { this.(ClassObjectInternal).lookup("__call__", _, _) } /** Holds if this class is an iterable. */ predicate isIterable() { @@ -462,17 +429,17 @@ class ClassValue extends Value { or this.hasAttribute("__getitem__") } - - /** Holds if this class is a container(). That is, does it have a __getitem__ method.*/ - predicate isContainer() { - exists(this.lookup("__getitem__")) - } - + + /** Holds if this class is a container(). That is, does it have a __getitem__ method. */ + predicate isContainer() { exists(this.lookup("__getitem__")) } + /** Holds if this class is probably a sequence. */ predicate isSequence() { - /* To determine whether something is a sequence or a mapping is not entirely clear, + /* + * To determine whether something is a sequence or a mapping is not entirely clear, * so we need to guess a bit. */ + this.getASuperType() = ClassValue::tuple() or this.getASuperType() = ClassValue::list() @@ -494,18 +461,15 @@ class ClassValue extends Value { this.hasAttribute("__reversed__") ) } - + /** Holds if this class is a mapping. */ predicate isMapping() { - this.hasAttribute("__getitem__") - and + this.hasAttribute("__getitem__") and not this.isSequence() } /** Holds if this class is a descriptor. */ - predicate isDescriptorType() { - this.hasAttribute("__get__") - } + predicate isDescriptorType() { this.hasAttribute("__get__") } /** Holds if this class is a context manager. */ predicate isContextManager() { @@ -513,7 +477,8 @@ class ClassValue extends Value { this.hasAttribute("__exit__") } - /** Gets the qualified name for this class. + /** + * Gets the qualified name for this class. * Should return the same name as the `__qualname__` attribute on classes in Python 3. */ string getQualifiedName() { @@ -523,62 +488,52 @@ class ClassValue extends Value { } /** Gets the MRO for this class */ - MRO getMro() { - result = Types::getMro(this) - } + MRO getMro() { result = Types::getMro(this) } - predicate failedInference(string reason) { - Types::failedInference(this, reason) - } + predicate failedInference(string reason) { Types::failedInference(this, reason) } /** Gets the nth immediate base type of this class. */ - ClassValue getBaseType(int n) { - result = Types::getBase(this, n) - } + ClassValue getBaseType(int n) { result = Types::getBase(this, n) } /** Gets an immediate base type of this class. */ - ClassValue getABaseType() { - result = Types::getBase(this, _) - } + ClassValue getABaseType() { result = Types::getBase(this, _) } - /** Holds if this class is a new style class. - * A new style class is one that implicitly or explicitly inherits from `object`. */ - predicate isNewStyle() { - Types::isNewStyle(this) - } + /** + * Holds if this class is a new style class. + * A new style class is one that implicitly or explicitly inherits from `object`. + */ + predicate isNewStyle() { Types::isNewStyle(this) } - /** Holds if this class is an old style class. - * An old style class is one that does not inherit from `object`. */ - predicate isOldStyle() { - Types::isOldStyle(this) - } + /** + * Holds if this class is an old style class. + * An old style class is one that does not inherit from `object`. + */ + predicate isOldStyle() { Types::isOldStyle(this) } /** Gets the scope associated with this class, if it is not a builtin class */ - ClassScope getScope() { - result = this.(PythonClassObjectInternal).getScope() - } + ClassScope getScope() { result = this.(PythonClassObjectInternal).getScope() } /** Gets the attribute declared in this class */ - Value declaredAttribute(string name) { - Types::declaredAttribute(this, name, result, _) - } + Value declaredAttribute(string name) { Types::declaredAttribute(this, name, result, _) } - /** Holds if this class has the attribute `name`, including + /** + * Holds if this class has the attribute `name`, including * attributes declared by super classes. */ - predicate hasAttribute(string name) { - this.getMro().declares(name) - } + predicate hasAttribute(string name) { this.getMro().declares(name) } - /** Holds if this class declares the attribute `name`, + /** + * Holds if this class declares the attribute `name`, * *not* including attributes declared by super classes. */ predicate declaresAttribute(string name) { this.(ClassObjectInternal).getClassDeclaration().declaresAttribute(name) } - /** Whether this class is a legal exception class. - * What constitutes a legal exception class differs between major versions */ + /** + * Whether this class is a legal exception class. + * What constitutes a legal exception class differs between major versions + */ predicate isLegalExceptionType() { not this.isNewStyle() or @@ -586,15 +541,13 @@ class ClassValue extends Value { or major_version() = 2 and this = ClassValue::tuple() } - } - -/** Class representing functions in the Python program, both Python and built-in. +/** + * Class representing functions in the Python program, both Python and built-in. * Note that this does not include other callables such as bound-methods. */ abstract class FunctionValue extends CallableValue { - abstract string getQualifiedName(); /** Gets the minimum number of parameters that can be correctly passed to this function */ @@ -603,13 +556,9 @@ abstract class FunctionValue extends CallableValue { /** Gets the maximum number of parameters that can be correctly passed to this function */ abstract int maxParameters(); - predicate isOverridingMethod() { - exists(Value f | this.overrides(f)) - } + predicate isOverridingMethod() { exists(Value f | this.overrides(f)) } - predicate isOverriddenMethod() { - exists(Value f | f.overrides(this)) - } + predicate isOverriddenMethod() { exists(Value f | f.overrides(this)) } /** Whether `name` is a legal argument name for this function */ bindingset[name] @@ -621,25 +570,22 @@ abstract class FunctionValue extends CallableValue { this.getScope().hasKwArg() } - /** Whether this is a "normal" method, that is, it is exists as a class attribute - * which is not a lambda and not the __new__ method. */ + /** + * Whether this is a "normal" method, that is, it is exists as a class attribute + * which is not a lambda and not the __new__ method. + */ predicate isNormalMethod() { exists(ClassValue cls, string name | cls.declaredAttribute(name) = this and name != "__new__" and - exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | - not origin instanceof Lambda - ) + exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | not origin instanceof Lambda) ) } } /** Class representing Python functions */ class PythonFunctionValue extends FunctionValue { - - PythonFunctionValue() { - this instanceof PythonFunctionObjectInternal - } + PythonFunctionValue() { this instanceof PythonFunctionObjectInternal } override string getQualifiedName() { result = this.(PythonFunctionObjectInternal).getScope().getQualifiedName() @@ -655,46 +601,30 @@ class PythonFunctionValue extends FunctionValue { override int maxParameters() { exists(Function f | f = this.getScope() and - if exists(f.getVararg()) then - result = 2147483647 // INT_MAX - else - result = count(f.getAnArg()) + if exists(f.getVararg()) + then result = 2147483647 // INT_MAX + else result = count(f.getAnArg()) ) } /** Gets a control flow node corresponding to a return statement in this function */ - ControlFlowNode getAReturnedNode() { - result = this.getScope().getAReturnValueFlowNode() - } - + ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() } } /** Class representing builtin functions, such as `len` or `print` */ class BuiltinFunctionValue extends FunctionValue { + BuiltinFunctionValue() { this instanceof BuiltinFunctionObjectInternal } - BuiltinFunctionValue() { - this instanceof BuiltinFunctionObjectInternal - } + override string getQualifiedName() { result = this.(BuiltinFunctionObjectInternal).getName() } - override string getQualifiedName() { - result = this.(BuiltinFunctionObjectInternal).getName() - } + override int minParameters() { none() } - override int minParameters() { - none() - } - - override int maxParameters() { - none() - } + override int maxParameters() { none() } } /** Class representing builtin methods, such as `list.append` or `set.add` */ class BuiltinMethodValue extends FunctionValue { - - BuiltinMethodValue() { - this instanceof BuiltinMethodObjectInternal - } + BuiltinMethodValue() { this instanceof BuiltinMethodObjectInternal } override string getQualifiedName() { exists(Builtin cls | @@ -704,46 +634,31 @@ class BuiltinMethodValue extends FunctionValue { ) } - override int minParameters() { - none() - } - - override int maxParameters() { - none() - } + override int minParameters() { none() } + override int maxParameters() { none() } } -/** A class representing sequence objects with a length and tracked items. +/** + * A class representing sequence objects with a length and tracked items. */ class SequenceValue extends Value { + SequenceValue() { this instanceof SequenceObjectInternal } - SequenceValue() { - this instanceof SequenceObjectInternal - } - - Value getItem(int n) { - result = this.(SequenceObjectInternal).getItem(n) - } - - int length() { - result = this.(SequenceObjectInternal).length() - } + Value getItem(int n) { result = this.(SequenceObjectInternal).getItem(n) } + int length() { result = this.(SequenceObjectInternal).length() } } /** A class representing tuple objects */ class TupleValue extends SequenceValue { - - TupleValue() { - this instanceof TupleObjectInternal - } - + TupleValue() { this instanceof TupleObjectInternal } } -/** A class representing strings, either present in the source as a literal, or - * in a builtin as a value. */ - +/** + * A class representing strings, either present in the source as a literal, or + * in a builtin as a value. + */ class StringValue extends Value { StringValue() { this instanceof BytesObjectInternal or @@ -757,7 +672,8 @@ class StringValue extends Value { } } -/** A class representing numbers (ints and floats), either present in the source as a literal, +/** + * A class representing numbers (ints and floats), either present in the source as a literal, * or in a builtin as a value. */ class NumericValue extends Value { @@ -767,102 +683,66 @@ class NumericValue extends Value { } /** Gets the integer-value if it is a constant integer, and it fits in a QL int */ - int getIntValue() { - result = this.(IntObjectInternal).intValue() - } + int getIntValue() { result = this.(IntObjectInternal).intValue() } /** Gets the float-value if it is a constant float */ - int getFloatValue() { - result = this.(FloatObjectInternal).floatValue() - } + int getFloatValue() { result = this.(FloatObjectInternal).floatValue() } } -/** A Python property: - * @property - * def f(): +/** + * A Python property: + * + * @property def f(): * .... * * https://docs.python.org/3/howto/descriptor.html#properties * https://docs.python.org/3/library/functions.html#property */ class PropertyValue extends Value { + PropertyValue() { this instanceof PropertyInternal } - PropertyValue() { - this instanceof PropertyInternal - } + CallableValue getGetter() { result = this.(PropertyInternal).getGetter() } - CallableValue getGetter(){ - result = this.(PropertyInternal).getGetter() - } - - CallableValue getSetter(){ - result = this.(PropertyInternal).getSetter() - } - - CallableValue getDeleter(){ - result = this.(PropertyInternal).getDeleter() - } + CallableValue getSetter() { result = this.(PropertyInternal).getSetter() } + CallableValue getDeleter() { result = this.(PropertyInternal).getDeleter() } } /** A method-resolution-order sequence of classes */ class MRO extends TClassList { - - string toString() { - result = this.(ClassList).toString() - } + string toString() { result = this.(ClassList).toString() } /** Gets the `n`th class in this MRO */ - ClassValue getItem(int n) { - result = this.(ClassList).getItem(n) - } + ClassValue getItem(int n) { result = this.(ClassList).getItem(n) } /** Holds if any class in this MRO declares the attribute `name` */ - predicate declares(string name) { - this.(ClassList).declares(name) - } + predicate declares(string name) { this.(ClassList).declares(name) } /** Gets the length of this MRO */ - int length() { - result = this.(ClassList).length() - } + int length() { result = this.(ClassList).length() } /** Holds if this MRO contains `cls` */ - predicate contains(ClassValue cls) { - this.(ClassList).contains(cls) - } + predicate contains(ClassValue cls) { this.(ClassList).contains(cls) } /** Gets the value from scanning for the attribute `name` in this MRO. */ - Value lookup(string name) { - this.(ClassList).lookup(name, result, _) - } + Value lookup(string name) { this.(ClassList).lookup(name, result, _) } - /** Gets the MRO formed by removing all classes before `cls` + /** + * Gets the MRO formed by removing all classes before `cls` * from this MRO. */ - MRO startingAt(ClassValue cls) { - result = this.(ClassList).startingAt(cls) - } - + MRO startingAt(ClassValue cls) { result = this.(ClassList).startingAt(cls) } } - module ClassValue { - /** Get the `ClassValue` for the `bool` class. */ - ClassValue bool() { - result = TBuiltinClassObject(Builtin::special("bool")) - } + ClassValue bool() { result = TBuiltinClassObject(Builtin::special("bool")) } /** Get the `ClassValue` for the `tuple` class. */ - ClassValue tuple() { - result = TBuiltinClassObject(Builtin::special("tuple")) - } + ClassValue tuple() { result = TBuiltinClassObject(Builtin::special("tuple")) } /** Get the `ClassValue` for the `list` class. */ - ClassValue list() { - result = TBuiltinClassObject(Builtin::special("list")) - } + ClassValue list() { result = TBuiltinClassObject(Builtin::special("list")) } /** Get the `ClassValue` for `xrange` (Python 2), or `range` (only Python 3) */ ClassValue range() { @@ -872,115 +752,74 @@ module ClassValue { } /** Get the `ClassValue` for the `dict` class. */ - ClassValue dict() { - result = TBuiltinClassObject(Builtin::special("dict")) - } + ClassValue dict() { result = TBuiltinClassObject(Builtin::special("dict")) } /** Get the `ClassValue` for the `set` class. */ - ClassValue set() { - result = TBuiltinClassObject(Builtin::special("set")) - } + ClassValue set() { result = TBuiltinClassObject(Builtin::special("set")) } /** Get the `ClassValue` for the `object` class. */ - ClassValue object() { - result = TBuiltinClassObject(Builtin::special("object")) - } + ClassValue object() { result = TBuiltinClassObject(Builtin::special("object")) } /** Get the `ClassValue` for the `int` class. */ - ClassValue int_() { - result = TBuiltinClassObject(Builtin::special("int")) - } + ClassValue int_() { result = TBuiltinClassObject(Builtin::special("int")) } /** Get the `ClassValue` for the `long` class. */ - ClassValue long() { - result = TBuiltinClassObject(Builtin::special("long")) - } + ClassValue long() { result = TBuiltinClassObject(Builtin::special("long")) } /** Get the `ClassValue` for the `float` class. */ - ClassValue float_() { - result = TBuiltinClassObject(Builtin::special("float")) - } + ClassValue float_() { result = TBuiltinClassObject(Builtin::special("float")) } /** Get the `ClassValue` for the `complex` class. */ - ClassValue complex() { - result = TBuiltinClassObject(Builtin::special("complex")) - } - + ClassValue complex() { result = TBuiltinClassObject(Builtin::special("complex")) } + /** Get the `ClassValue` for the `bytes` class (also called `str` in Python 2). */ - ClassValue bytes() { - result = TBuiltinClassObject(Builtin::special("bytes")) - } + ClassValue bytes() { result = TBuiltinClassObject(Builtin::special("bytes")) } - /** Get the `ClassValue` for the class of unicode strings. - * `str` in Python 3 and `unicode` in Python 2. */ - ClassValue unicode() { - result = TBuiltinClassObject(Builtin::special("unicode")) - } + /** + * Get the `ClassValue` for the class of unicode strings. + * `str` in Python 3 and `unicode` in Python 2. + */ + ClassValue unicode() { result = TBuiltinClassObject(Builtin::special("unicode")) } - /** Get the `ClassValue` for the `str` class. This is `bytes` in Python 2, - * and `str` in Python 3. */ - ClassValue str() { - if major_version() = 2 then - result = bytes() - else - result = unicode() - } + /** + * Get the `ClassValue` for the `str` class. This is `bytes` in Python 2, + * and `str` in Python 3. + */ + ClassValue str() { if major_version() = 2 then result = bytes() else result = unicode() } /** Get the `ClassValue` for the `property` class. */ - ClassValue property() { - result = TBuiltinClassObject(Builtin::special("property")) - } + ClassValue property() { result = TBuiltinClassObject(Builtin::special("property")) } /** Get the `ClassValue` for the class of Python functions. */ - ClassValue functionType() { - result = TBuiltinClassObject(Builtin::special("FunctionType")) - } + ClassValue functionType() { result = TBuiltinClassObject(Builtin::special("FunctionType")) } /** Get the `ClassValue` for the class of builtin functions. */ - ClassValue builtinFunction() { - result = Value::named("len").getClass() - } + ClassValue builtinFunction() { result = Value::named("len").getClass() } /** Get the `ClassValue` for the `generatorType` class. */ - ClassValue generator() { - result = TBuiltinClassObject(Builtin::special("generator")) - } + ClassValue generator() { result = TBuiltinClassObject(Builtin::special("generator")) } /** Get the `ClassValue` for the `type` class. */ - ClassValue type() { - result = TType() - } + ClassValue type() { result = TType() } /** Get the `ClassValue` for `ClassType`. */ - ClassValue classType() { - result = TBuiltinClassObject(Builtin::special("ClassType")) - } + ClassValue classType() { result = TBuiltinClassObject(Builtin::special("ClassType")) } /** Get the `ClassValue` for `InstanceType`. */ - ClassValue instanceType() { - result = TBuiltinClassObject(Builtin::special("InstanceType")) - } + ClassValue instanceType() { result = TBuiltinClassObject(Builtin::special("InstanceType")) } /** Get the `ClassValue` for `super`. */ - ClassValue super_() { - result = TBuiltinClassObject(Builtin::special("super")) - } + ClassValue super_() { result = TBuiltinClassObject(Builtin::special("super")) } /** Get the `ClassValue` for the `classmethod` class. */ - ClassValue classmethod() { - result = TBuiltinClassObject(Builtin::special("ClassMethod")) - } + ClassValue classmethod() { result = TBuiltinClassObject(Builtin::special("ClassMethod")) } /** Get the `ClassValue` for the `staticmethod` class. */ - ClassValue staticmethod() { - result = TBuiltinClassObject(Builtin::special("StaticMethod")) - } + ClassValue staticmethod() { result = TBuiltinClassObject(Builtin::special("StaticMethod")) } /** Get the `ClassValue` for the `MethodType` class. */ - pragma [noinline] - ClassValue methodType() { - result = TBuiltinClassObject(Builtin::special("MethodType")) - } + pragma[noinline] + ClassValue methodType() { result = TBuiltinClassObject(Builtin::special("MethodType")) } /** Get the `ClassValue` for the `MethodDescriptorType` class. */ ClassValue methodDescriptorType() { @@ -993,59 +832,37 @@ module ClassValue { } /** Get the `ClassValue` for the `StopIteration` class. */ - ClassValue stopIteration() { - result = TBuiltinClassObject(Builtin::builtin("StopIteration")) - } + ClassValue stopIteration() { result = TBuiltinClassObject(Builtin::builtin("StopIteration")) } /** Get the `ClassValue` for the class of modules. */ - ClassValue module_() { - result = TBuiltinClassObject(Builtin::special("ModuleType")) - } + ClassValue module_() { result = TBuiltinClassObject(Builtin::special("ModuleType")) } /** Get the `ClassValue` for the `Exception` class. */ - ClassValue exception() { - result = TBuiltinClassObject(Builtin::special("Exception")) - } + ClassValue exception() { result = TBuiltinClassObject(Builtin::special("Exception")) } /** Get the `ClassValue` for the `BaseException` class. */ - ClassValue baseException() { - result = TBuiltinClassObject(Builtin::special("BaseException")) - } + ClassValue baseException() { result = TBuiltinClassObject(Builtin::special("BaseException")) } /** Get the `ClassValue` for the `NoneType` class. */ - ClassValue nonetype() { - result = TBuiltinClassObject(Builtin::special("NoneType")) - } + ClassValue nonetype() { result = TBuiltinClassObject(Builtin::special("NoneType")) } /** Get the `ClassValue` for the `TypeError` class */ - ClassValue typeError() { - result = TBuiltinClassObject(Builtin::special("TypeError")) - } + ClassValue typeError() { result = TBuiltinClassObject(Builtin::special("TypeError")) } /** Get the `ClassValue` for the `NameError` class. */ - ClassValue nameError() { - result = TBuiltinClassObject(Builtin::builtin("NameError")) - } + ClassValue nameError() { result = TBuiltinClassObject(Builtin::builtin("NameError")) } /** Get the `ClassValue` for the `AttributeError` class. */ - ClassValue attributeError() { - result = TBuiltinClassObject(Builtin::builtin("AttributeError")) - } + ClassValue attributeError() { result = TBuiltinClassObject(Builtin::builtin("AttributeError")) } /** Get the `ClassValue` for the `KeyError` class. */ - ClassValue keyError() { - result = TBuiltinClassObject(Builtin::builtin("KeyError")) - } + ClassValue keyError() { result = TBuiltinClassObject(Builtin::builtin("KeyError")) } /** Get the `ClassValue` for the `LookupError` class. */ - ClassValue lookupError() { - result = TBuiltinClassObject(Builtin::builtin("LookupError")) - } + ClassValue lookupError() { result = TBuiltinClassObject(Builtin::builtin("LookupError")) } /** Get the `ClassValue` for the `IOError` class. */ - ClassValue ioError() { - result = TBuiltinClassObject(Builtin::builtin("IOError")) - } + ClassValue ioError() { result = TBuiltinClassObject(Builtin::builtin("IOError")) } /** Get the `ClassValue` for the `NotImplementedError` class. */ ClassValue notImplementedError() { @@ -1053,9 +870,7 @@ module ClassValue { } /** Get the `ClassValue` for the `ImportError` class. */ - ClassValue importError() { - result = TBuiltinClassObject(Builtin::builtin("ImportError")) - } + ClassValue importError() { result = TBuiltinClassObject(Builtin::builtin("ImportError")) } /** Get the `ClassValue` for the `UnicodeEncodeError` class. */ ClassValue unicodeEncodeError() { @@ -1066,5 +881,4 @@ module ClassValue { ClassValue unicodeDecodeError() { result = TBuiltinClassObject(Builtin::builtin("UnicodeDecodeError")) } - } diff --git a/python/ql/src/semmle/python/objects/ObjectInternal.qll b/python/ql/src/semmle/python/objects/ObjectInternal.qll index 09f6e883ae1..de4e5b80b54 100644 --- a/python/ql/src/semmle/python/objects/ObjectInternal.qll +++ b/python/ql/src/semmle/python/objects/ObjectInternal.qll @@ -16,16 +16,17 @@ import semmle.python.objects.Constants import semmle.python.objects.Sequences import semmle.python.objects.Descriptors - class ObjectInternal extends TObject { - abstract string toString(); - /** The boolean value of this object, this may be both - * true and false if the "object" represents a set of possible objects. */ + /** + * The boolean value of this object, this may be both + * true and false if the "object" represents a set of possible objects. + */ abstract boolean booleanValue(); - /** Holds if this object is introduced into the code base at `node` given the `context` + /** + * Holds if this object is introduced into the code base at `node` given the `context` * This means that `node`, in `context`, points-to this object, but the object has not flowed * there from anywhere else. * Examples: @@ -41,22 +42,25 @@ class ObjectInternal extends TObject { /** True if this "object" is a class. That is, its class inherits from `type` */ abstract boolean isClass(); - /** Gets the class of this object. */ + /** Gets the class of this object. */ abstract ObjectInternal getClass(); - /** True if this "object" can be meaningfully analysed to determine the boolean value of + /** + * True if this "object" can be meaningfully analysed to determine the boolean value of * equality tests on it. * For example, `None` or `int` can be, but `int()` or an unknown string cannot. */ abstract predicate notTestableForEquality(); - /** Gets the `Builtin` for this object, if any. + /** + * Gets the `Builtin` for this object, if any. * Objects (except unknown and undefined values) should attempt to return * exactly one result for either this method or `getOrigin()`. */ abstract Builtin getBuiltin(); - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * object, if it has a meaningful location in the source code. * This method exists primarily for providing backwards compatibility and * locations for source objects. @@ -64,7 +68,8 @@ class ObjectInternal extends TObject { */ abstract ControlFlowNode getOrigin(); - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj`. * * This is the context-insensitive version. @@ -72,7 +77,8 @@ class ObjectInternal extends TObject { */ abstract predicate callResult(ObjectInternal obj, CfgOrigin origin); - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj` with callee context `callee`. * * This is the context-sensitive version. @@ -80,34 +86,36 @@ class ObjectInternal extends TObject { */ abstract predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin); - /** The integer value of things that have integer values and whose integer value is + /** + * The integer value of things that have integer values and whose integer value is * tracked. * That is, some ints, mainly small numbers, and bools. */ abstract int intValue(); - /** The string value of things that have string values. + /** + * The string value of things that have string values. * That is, strings. */ abstract string strValue(); - /** Holds if the function `scope` is called when this object is called and `paramOffset` + /** + * Holds if the function `scope` is called when this object is called and `paramOffset` * is the difference from the parameter position and the argument position. * For a normal function `paramOffset` is 0. For classes and bound-methods it is 1. * Used by points-to to help determine flow from arguments to parameters. */ abstract predicate calleeAndOffset(Function scope, int paramOffset); - final predicate isBuiltin() { - exists(this.getBuiltin()) - } + final predicate isBuiltin() { exists(this.getBuiltin()) } - /** Holds if the result of getting the attribute `name` is `value` and that `value` comes + /** + * Holds if the result of getting the attribute `name` is `value` and that `value` comes * from `origin`. Note this is *not* the same as class lookup. For example - * for an object `x` the attribute `name` (`x.name`) may refer to a bound-method, an attribute of the + * for an object `x` the attribute `name` (`x.name`) may refer to a bound-method, an attribute of the * instance, or an attribute of the class. */ - pragma [nomagic] + pragma[nomagic] abstract predicate attribute(string name, ObjectInternal value, CfgOrigin origin); /** Holds if the attributes of this object are wholly or partly unknowable */ @@ -116,59 +124,71 @@ class ObjectInternal extends TObject { /** Holds if the result of subscripting this object are wholly or partly unknowable */ abstract predicate subscriptUnknown(); - /** For backwards compatibility shim -- Not all objects have a "source". + /** + * For backwards compatibility shim -- Not all objects have a "source". * Objects (except unknown and undefined values) should attempt to return * exactly one result for this method. - * */ + */ @py_object getSource() { result = this.getOrigin() or result = this.getBuiltin() } - /** Holds if this object is a descriptor. + /** + * Holds if this object is a descriptor. * Holds, for example, for functions and properties and not for integers. */ abstract boolean isDescriptor(); - /** Holds if the result of attribute access on the class holding this descriptor is `value`, originating at `origin` + /** + * Holds if the result of attribute access on the class holding this descriptor is `value`, originating at `origin` * For example, although `T.__dict__['name'] = classmethod(f)`, `T.name` is a bound-method, binding `f` and `T` */ pragma[nomagic] abstract predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin); - /** Holds if the result of attribute access on an instance of a class holding this descriptor is `value`, originating at `origin` + /** + * Holds if the result of attribute access on an instance of a class holding this descriptor is `value`, originating at `origin` * For example, with `T.__dict__['name'] = classmethod(f)`, `T().name` is a bound-method, binding `f` and `T` */ pragma[nomagic] - abstract predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin); + abstract predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ); - /** Holds if attribute lookup on this object may "bind" `instance` to `descriptor`. + /** + * Holds if attribute lookup on this object may "bind" `instance` to `descriptor`. * Here "bind" means that `instance` is passed to the `descriptor.__get__()` method * at runtime. The term "bind" is used as this most likely results in a bound-method. */ abstract predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor); - /** Gets the length of the sequence that this "object" represents. + /** + * Gets the length of the sequence that this "object" represents. * Always returns a value for a sequence, will be -1 if the object has no fixed length. */ abstract int length(); - /** Holds if the object `function` is called when this object is called and `paramOffset` + /** + * Holds if the object `function` is called when this object is called and `paramOffset` * is the difference from the parameter position and the argument position. * For a normal function `paramOffset` is 0. For classes and bound-methods it is 1. * This is used to implement the `CallableValue` public API. */ predicate functionAndOffset(CallableObjectInternal function, int offset) { none() } - /** Holds if this 'object' represents an entity that should be exposed to the legacy points_to API + /** + * Holds if this 'object' represents an entity that should be exposed to the legacy points_to API * This should hold for almost all objects that do not have an underlying DB object representing their source, * for example `super` objects and bound-method. This should not hold for objects that are inferred to exists by - * an import statements or the like, but which aren't in the database. */ - /* This predicate can be removed when the legacy points_to API is removed. */ + * an import statements or the like, but which aren't in the database. + */ + /* This predicate can be removed when the legacy points_to API is removed. */ abstract predicate useOriginAsLegacyObject(); - /** Gets the name of this of this object if it has a meaningful name. + /** + * Gets the name of this of this object if it has a meaningful name. * Note that the name of an object is not necessarily the name by which it is called * For example the function named `posixpath.join` will be called `os.path.join`. */ @@ -176,50 +196,36 @@ class ObjectInternal extends TObject { abstract predicate contextSensitiveCallee(); - /** Gets the 'object' resulting from iterating over this object. + /** + * Gets the 'object' resulting from iterating over this object. * Used in the context `for i in this:`. The result is the 'object' * assigned to `i`. */ abstract ObjectInternal getIterNext(); /** Holds if this value has the attribute `name` */ - predicate hasAttribute(string name) { - this.(ObjectInternal).attribute(name, _, _) - } + predicate hasAttribute(string name) { this.(ObjectInternal).attribute(name, _, _) } abstract predicate isNotSubscriptedType(); - } - class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject { + override Builtin getBuiltin() { this = TBuiltinOpaqueObject(result) } - override Builtin getBuiltin() { - this = TBuiltinOpaqueObject(result) - } - - override string toString() { - result = this.getBuiltin().getClass().getName() + " object" - } + override string toString() { result = this.getBuiltin().getClass().getName() + " object" } override boolean booleanValue() { // TO DO ... Depends on class. `result = this.getClass().instancesBooleanValue()` result = maybe() } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } - override ObjectInternal getClass() { - result = TBuiltinClassObject(this.getBuiltin().getClass()) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } @@ -231,46 +237,47 @@ class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = ObjectInternal::fromBuiltin(this.getBuiltin().getMember(name)) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override predicate subscriptUnknown() { - exists(this.getBuiltin().getItem(_)) - } + override predicate subscriptUnknown() { exists(this.getBuiltin().getItem(_)) } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } - override string getName() { - result = this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } override predicate contextSensitiveCallee() { none() } @@ -279,39 +286,24 @@ class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } - class UnknownInternal extends ObjectInternal, TUnknown { + override string toString() { result = "Unknown value" } - override string toString() { - result = "Unknown value" - } + override boolean booleanValue() { result = maybe() } - override boolean booleanValue() { - result = maybe() - } - - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } - override ObjectInternal getClass() { - result = TUnknownClass() - } + override ObjectInternal getClass() { result = TUnknownClass() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } - override Builtin getBuiltin() { - result = Builtin::unknown() - } + override Builtin getBuiltin() { result = Builtin::unknown() } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() @@ -321,37 +313,40 @@ class UnknownInternal extends ObjectInternal, TUnknown { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { result = -1 } @@ -364,38 +359,24 @@ class UnknownInternal extends ObjectInternal, TUnknown { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } class UndefinedInternal extends ObjectInternal, TUndefined { + override string toString() { result = "Undefined variable" } - override string toString() { - result = "Undefined variable" - } + override boolean booleanValue() { none() } - override boolean booleanValue() { - none() - } - - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override predicate notTestableForEquality() { any() } - override ObjectInternal getClass() { - none() - } + override ObjectInternal getClass() { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -407,37 +388,40 @@ class UndefinedInternal extends ObjectInternal, TUndefined { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } override boolean isDescriptor() { none() } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } @@ -445,39 +429,31 @@ class UndefinedInternal extends ObjectInternal, TUndefined { override predicate useOriginAsLegacyObject() { none() } - /** Holds if this object requires context to determine the object resulting from a call to it. - * True for most callables. */ + /** + * Holds if this object requires context to determine the object resulting from a call to it. + * True for most callables. + */ override predicate contextSensitiveCallee() { none() } override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } module ObjectInternal { - ObjectInternal bool(boolean b) { b = true and result = TTrue() or b = false and result = TFalse() } - ObjectInternal none_() { - result = TNone() - } + ObjectInternal none_() { result = TNone() } - ObjectInternal unknown() { - result = TUnknown() - } + ObjectInternal unknown() { result = TUnknown() } - ClassObjectInternal unknownClass() { - result = TUnknownClass() - } + ClassObjectInternal unknownClass() { result = TUnknownClass() } - ObjectInternal undefined() { - result = TUndefined() - } + ObjectInternal undefined() { result = TUndefined() } ObjectInternal builtin(string name) { result = TBuiltinClassObject(Builtin::builtin(name)) @@ -490,12 +466,10 @@ module ObjectInternal { } ObjectInternal sysModules() { - result = TBuiltinOpaqueObject(Builtin::special("sys").getMember("modules")) + result = TBuiltinOpaqueObject(Builtin::special("sys").getMember("modules")) } - ObjectInternal fromInt(int n) { - result = TInt(n) - } + ObjectInternal fromInt(int n) { result = TInt(n) } ObjectInternal fromBuiltin(Builtin b) { b = result.getBuiltin() and @@ -506,67 +480,38 @@ module ObjectInternal { b = Builtin::special("sys").getMember("version_info") and result = TSysVersionInfo() } - ObjectInternal classMethod() { - result = TBuiltinClassObject(Builtin::special("ClassMethod")) - } + ObjectInternal classMethod() { result = TBuiltinClassObject(Builtin::special("ClassMethod")) } - ObjectInternal staticMethod() { - result = TBuiltinClassObject(Builtin::special("StaticMethod")) - } + ObjectInternal staticMethod() { result = TBuiltinClassObject(Builtin::special("StaticMethod")) } - ObjectInternal boundMethod() { - result = TBuiltinClassObject(Builtin::special("MethodType")) - } + ObjectInternal boundMethod() { result = TBuiltinClassObject(Builtin::special("MethodType")) } - ObjectInternal moduleType() { - result = TBuiltinClassObject(Builtin::special("ModuleType")) - } + ObjectInternal moduleType() { result = TBuiltinClassObject(Builtin::special("ModuleType")) } - ObjectInternal noneType() { - result = TBuiltinClassObject(Builtin::special("NoneType")) - } + ObjectInternal noneType() { result = TBuiltinClassObject(Builtin::special("NoneType")) } - ObjectInternal type() { - result = TType() - } + ObjectInternal type() { result = TType() } - ObjectInternal property() { - result = TBuiltinClassObject(Builtin::special("property")) - } + ObjectInternal property() { result = TBuiltinClassObject(Builtin::special("property")) } - ObjectInternal superType() { - result = TBuiltinClassObject(Builtin::special("super")) - } + ObjectInternal superType() { result = TBuiltinClassObject(Builtin::special("super")) } /** The old-style class type (Python 2 only) */ - ObjectInternal classType() { - result = TBuiltinClassObject(Builtin::special("ClassType")) - } - - ObjectInternal emptyTuple() { - result.(BuiltinTupleObjectInternal).length() = 0 - } + ObjectInternal classType() { result = TBuiltinClassObject(Builtin::special("ClassType")) } + ObjectInternal emptyTuple() { result.(BuiltinTupleObjectInternal).length() = 0 } } class DecoratedFunction extends ObjectInternal, TDecoratedFunction { + CallNode getDecoratorCall() { this = TDecoratedFunction(result) } - - CallNode getDecoratorCall() { - this = TDecoratedFunction(result) - } - - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } private ObjectInternal decoratedObject() { PointsTo::pointsTo(this.getDecoratorCall().getArg(0), _, result, _) } - override string getName() { - result = this.decoratedObject().getName() - } + override string getName() { result = this.decoratedObject().getName() } override string toString() { result = "Decorated " + this.decoratedObject().toString() @@ -576,17 +521,13 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { override boolean booleanValue() { result = true } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override ObjectInternal getClass() { result = TUnknownClass() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { none() } @@ -598,25 +539,15 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - result = this.getDecoratorCall() - } + override ControlFlowNode getOrigin() { result = this.getDecoratorCall() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } override predicate attributesUnknown() { none() } @@ -624,11 +555,22 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } @@ -639,17 +581,13 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } /** Helper for boolean predicates returning both `true` and `false` */ -boolean maybe() { - result = true or result = false -} +boolean maybe() { result = true or result = false } /** Helper for attributes */ -pragma [nomagic] +pragma[nomagic] predicate receiver_type(AttrNode attr, string name, ObjectInternal value, ClassObjectInternal cls) { PointsToInternal::pointsTo(attr.getObject(name), _, value, _) and value.getClass() = cls } - diff --git a/python/ql/src/semmle/python/objects/Sequences.qll b/python/ql/src/semmle/python/objects/Sequences.qll index d6c08315b85..1259aadc07b 100644 --- a/python/ql/src/semmle/python/objects/Sequences.qll +++ b/python/ql/src/semmle/python/objects/Sequences.qll @@ -1,9 +1,4 @@ - import python - - - - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -12,7 +7,6 @@ private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins abstract class SequenceObjectInternal extends ObjectInternal { - /** Gets the `n`th item of this sequence, if one exists. */ abstract ObjectInternal getItem(int n); @@ -24,45 +18,50 @@ abstract class SequenceObjectInternal extends ObjectInternal { override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override string getName() { none() } override predicate contextSensitiveCallee() { none() } override ObjectInternal getIterNext() { result = this.getItem(_) } - } abstract class TupleObjectInternal extends SequenceObjectInternal { - - override string toString() { - result = "(" + this.contents(0) + ")" - } + override string toString() { result = "(" + this.contents(0) + ")" } private string contents(int n) { n < 4 and n = this.length() and result = "" or - n = 3 and this.length() > 3 and result = (this.length()-3).toString() + " more..." + n = 3 and this.length() > 3 and result = (this.length() - 3).toString() + " more..." or - result = this.item(n) + ", " + this.contents(n+1) + result = this.item(n) + ", " + this.contents(n + 1) } private string item(int n) { exists(ObjectInternal item | item = this.getItem(n) | // To avoid infinite recursion, nested tuples are replaced with the string "...". - if item instanceof TupleObjectInternal then - result = "(...)" - else - result = item.toString() + if item instanceof TupleObjectInternal then result = "(...)" else result = item.toString() ) or - n in [0..this.length()-1] and - not exists(this.getItem(n)) and result = "?" + n in [0 .. this.length() - 1] and + not exists(this.getItem(n)) and + result = "?" } /** Gets the class declaration for this object, if it is a declared class. */ @@ -73,60 +72,59 @@ abstract class TupleObjectInternal extends SequenceObjectInternal { override ObjectInternal getClass() { result = ObjectInternal::builtin("tuple") } - /** True if this "object" can be meaningfully analysed for + /** + * True if this "object" can be meaningfully analysed for * truth or false in comparisons. For example, `None` or `int` can be, but `int()` * or an unknown string cannot. */ override predicate notTestableForEquality() { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj`. */ override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj` with callee context `callee`. */ - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, ints and bools. */ override int intValue() { none() } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, strings. */ override string strValue() { none() } override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } - } /** A tuple built-in to the interpreter, including the empty tuple. */ class BuiltinTupleObjectInternal extends TBuiltinTuple, TupleObjectInternal { + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override Builtin getBuiltin() { this = TBuiltinTuple(result) } - override Builtin getBuiltin() { - this = TBuiltinTuple(result) - } + override ControlFlowNode getOrigin() { none() } - override ControlFlowNode getOrigin() { - none() - } - - override ObjectInternal getItem(int n) { - result.getBuiltin() = this.getBuiltin().getItem(n) - } + override ObjectInternal getItem(int n) { result.getBuiltin() = this.getBuiltin().getItem(n) } override int length() { exists(Builtin b | @@ -138,23 +136,17 @@ class BuiltinTupleObjectInternal extends TBuiltinTuple, TupleObjectInternal { override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } /** A tuple declared by a tuple expression in the Python source code */ class PythonTupleObjectInternal extends TPythonTuple, TupleObjectInternal { - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TPythonTuple(node, context) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TPythonTuple(result, _) - } + override ControlFlowNode getOrigin() { this = TPythonTuple(result, _) } override ObjectInternal getItem(int n) { exists(TupleNode t, PointsToContext context | @@ -173,51 +165,37 @@ class PythonTupleObjectInternal extends TPythonTuple, TupleObjectInternal { override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } /** A tuple created by a `*` parameter */ -class VarargsTupleObjectInternal extends TVarargsTuple, TupleObjectInternal { +class VarargsTupleObjectInternal extends TVarargsTuple, TupleObjectInternal { + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } - - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override ObjectInternal getItem(int n) { exists(CallNode call, PointsToContext context, int offset, int length | this = TVarargsTuple(call, context, offset, length) and n < length and - InterProceduralPointsTo::positional_argument_points_to(call, offset+n, context, result, _) + InterProceduralPointsTo::positional_argument_points_to(call, offset + n, context, result, _) ) } - override int length() { - this = TVarargsTuple(_, _, _, result) - } + override int length() { this = TVarargsTuple(_, _, _, result) } override predicate useOriginAsLegacyObject() { any() } override predicate isNotSubscriptedType() { any() } - } - -/** The `sys.version_info` object. We treat this specially to prevent premature pruning and +/** + * The `sys.version_info` object. We treat this specially to prevent premature pruning and * false positives when we are unsure of the actual version of Python that the code is expecting. */ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectInternal { - - override string toString() { - result = "sys.version_info" - } + override string toString() { result = "sys.version_info" } override ObjectInternal getItem(int n) { n = 0 and result = TInt(major_version()) @@ -235,39 +213,45 @@ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectIntern /** True if this "object" is a class. */ override boolean isClass() { result = false } - override ObjectInternal getClass() { - result.getBuiltin() = this.getClassDeclaration() - } + override ObjectInternal getClass() { result.getBuiltin() = this.getClassDeclaration() } override predicate notTestableForEquality() { none() } - /** Gets the `Builtin` for this object, if any. + /** + * Gets the `Builtin` for this object, if any. * Objects (except unknown and undefined values) should attempt to return * exactly one result for either this method or `getOrigin()`. */ override Builtin getBuiltin() { none() } - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * objects. */ override ControlFlowNode getOrigin() { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj`. */ override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj` with callee context `callee`. */ - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, ints and bools. */ override int intValue() { none() } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, strings. */ override string strValue() { none() } @@ -280,7 +264,8 @@ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectIntern override predicate subscriptUnknown() { none() } - /** Gets the length of the sequence that this "object" represents. + /** + * Gets the length of the sequence that this "object" represents. * Always returns a value for a sequence, will be -1 if object has no fixed length. */ override int length() { result = 5 } @@ -290,5 +275,4 @@ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectIntern override predicate useOriginAsLegacyObject() { any() } override predicate isNotSubscriptedType() { any() } - } diff --git a/python/ql/src/semmle/python/objects/TObject.qll b/python/ql/src/semmle/python/objects/TObject.qll index 48cd8784dae..15035bf722a 100644 --- a/python/ql/src/semmle/python/objects/TObject.qll +++ b/python/ql/src/semmle/python/objects/TObject.qll @@ -4,239 +4,193 @@ private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext -/** Internal type backing `ObjectInternal` and `Value` +/** + * Internal type backing `ObjectInternal` and `Value` * See `ObjectInternal.qll` for an explanation of the API. */ -cached newtype TObject = +cached +newtype TObject = /* Builtin class objects */ TBuiltinClassObject(Builtin bltn) { bltn.isClass() and not bltn = Builtin::unknownType() and not bltn = Builtin::special("type") - } - or + } or /* Builtin function objects (module members) */ - TBuiltinFunctionObject(Builtin bltn) { bltn.isFunction() } - or + TBuiltinFunctionObject(Builtin bltn) { bltn.isFunction() } or /* Builtin method objects (class members) */ - TBuiltinMethodObject(Builtin bltn) { bltn.isMethod() } - or + TBuiltinMethodObject(Builtin bltn) { bltn.isMethod() } or /* Builtin module objects */ - TBuiltinModuleObject(Builtin bltn) { bltn.isModule() } - or + TBuiltinModuleObject(Builtin bltn) { bltn.isModule() } or /* Other builtin objects from the interpreter */ TBuiltinOpaqueObject(Builtin bltn) { - not bltn.isClass() and not bltn.isFunction() and - not bltn.isMethod() and not bltn.isModule() and + not bltn.isClass() and + not bltn.isFunction() and + not bltn.isMethod() and + not bltn.isModule() and not bltn.getClass() = Builtin::special("tuple") and not exists(bltn.intValue()) and not exists(bltn.floatValue()) and not exists(bltn.strValue()) and not py_special_objects(bltn, _) - } - or + } or /* Python function objects (including lambdas) */ - TPythonFunctionObject(ControlFlowNode callable) { - callable.getNode() instanceof CallableExpr - } - or + TPythonFunctionObject(ControlFlowNode callable) { callable.getNode() instanceof CallableExpr } or /* Python class objects */ - TPythonClassObject(ControlFlowNode classexpr) { - classexpr.getNode() instanceof ClassExpr - } - or + TPythonClassObject(ControlFlowNode classexpr) { classexpr.getNode() instanceof ClassExpr } or /* Package objects */ - TPackageObject(Folder f) { - isPreferredModuleForName(f, _) - } - or + TPackageObject(Folder f) { isPreferredModuleForName(f, _) } or /* Python module objects */ TPythonModule(Module m) { - not m.isPackage() and isPreferredModuleForName(m.getFile(), _) and + not m.isPackage() and + isPreferredModuleForName(m.getFile(), _) and not exists(SyntaxError se | se.getFile() = m.getFile()) - } - or + } or /* `True` */ - TTrue() - or + TTrue() or /* `False` */ - TFalse() - or + TFalse() or /* `None` */ - TNone() - or + TNone() or /* Represents any value about which nothing useful is known */ - TUnknown() - or + TUnknown() or /* Represents any value known to be a class, but not known to be any specific class */ - TUnknownClass() - or + TUnknownClass() or /* Represents the absence of a value. Used by points-to for tracking undefined variables */ - TUndefined() - or + TUndefined() or /* The integer `n` */ TInt(int n) { // Powers of 2 are used for flags - is_power_2(n) or + is_power_2(n) + or // And all combinations of flags up to 2^8 - n in [0..511] or + n in [0 .. 511] + or // Any number explicitly mentioned in the source code. exists(IntegerLiteral num | - n = num.getValue() or - exists(UnaryExpr neg | neg.getOp() instanceof USub and neg.getOperand() = num) - and n = -num.getN().toInt() + n = num.getValue() + or + exists(UnaryExpr neg | neg.getOp() instanceof USub and neg.getOperand() = num) and + n = -num.getN().toInt() ) or n = any(Builtin b).intValue() - } - or + } or /* The float `f` */ - TFloat(float f) { - f = any(FloatLiteral num).getValue() - } - or + TFloat(float f) { f = any(FloatLiteral num).getValue() } or /* The unicode string `s` */ TUnicode(string s) { // Any string explicitly mentioned in the source code. - exists(StrConst str | + exists(StrConst str | s = str.getText() and str.isUnicode() ) or // Any string from the library put in the DB by the extractor. exists(Builtin b | - s = b.strValue() and + s = b.strValue() and b.getClass() = Builtin::special("unicode") ) or s = "__main__" - } - or + } or /* The byte string `s` */ TBytes(string s) { // Any string explicitly mentioned in the source code. - exists(StrConst str | + exists(StrConst str | s = str.getText() and not str.isUnicode() ) or // Any string from the library put in the DB by the extractor. exists(Builtin b | - s = b.strValue() and + s = b.strValue() and b.getClass() = Builtin::special("bytes") ) or s = "__main__" - } - or + } or /* An instance of `cls`, instantiated at `instantiation` given the `context`. */ TSpecificInstance(ControlFlowNode instantiation, ClassObjectInternal cls, PointsToContext context) { PointsToInternal::pointsTo(instantiation.(CallNode).getFunction(), context, cls, _) and cls.isSpecial() = false or literal_instantiation(instantiation, cls, context) - } - or + } or /* A non-specific instance `cls` which enters the scope at `def` given the callee `context`. */ TSelfInstance(ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls) { self_parameter(def, context, cls) - } - or + } or /* A bound method */ TBoundMethod(ObjectInternal self, CallableObjectInternal function) { any(ObjectInternal obj).binds(self, _, function) and function.isDescriptor() = true - } - or + } or /* Represents any value whose class is known, but nothing else */ TUnknownInstance(BuiltinClassObjectInternal cls) { cls != ObjectInternal::superType() and cls != ObjectInternal::builtin("bool") and cls != ObjectInternal::noneType() - } - or + } or /* Represents an instance of `super` */ TSuperInstance(ObjectInternal self, ClassObjectInternal startclass) { super_instantiation(_, self, startclass, _) - } - or + } or /* Represents an instance of `classmethod` */ TClassMethod(CallNode instantiation, CallableObjectInternal function) { class_method(instantiation, function, _) - } - or + } or /* Represents an instance of `staticmethod` */ TStaticMethod(CallNode instantiation, CallableObjectInternal function) { static_method(instantiation, function, _) - } - or + } or /* Represents a builtin tuple */ - TBuiltinTuple(Builtin bltn) { - bltn.getClass() = Builtin::special("tuple") - } - or + TBuiltinTuple(Builtin bltn) { bltn.getClass() = Builtin::special("tuple") } or /* Represents a tuple in the Python source */ TPythonTuple(TupleNode origin, PointsToContext context) { origin.isLoad() and context.appliesTo(origin) - } - or + } or /* Varargs tuple */ TVarargsTuple(CallNode call, PointsToContext context, int offset, int length) { InterProceduralPointsTo::varargs_tuple(call, context, _, _, offset, length) - } - or + } or /* `type` */ - TType() - or + TType() or /* Represents an instance of `property` */ TProperty(CallNode call, Context ctx, CallableObjectInternal getter) { PointsToInternal::pointsTo(call.getFunction(), ctx, ObjectInternal::property(), _) and PointsToInternal::pointsTo(call.getArg(0), ctx, getter, _) - } - or + } or /* Represents the `setter` or `deleter` method of a property object. */ TPropertySetterOrDeleter(PropertyInternal property, string method) { - exists(AttrNode attr | - PointsToInternal::pointsTo(attr.getObject(method), _, property, _) - ) and - ( method = "setter" or method = "deleter" ) - } - or + exists(AttrNode attr | PointsToInternal::pointsTo(attr.getObject(method), _, property, _)) and + (method = "setter" or method = "deleter") + } or /* Represents a dynamically created class */ TDynamicClass(CallNode instantiation, ClassObjectInternal metacls, PointsToContext context) { PointsToInternal::pointsTo(instantiation.getFunction(), context, metacls, _) and not count(instantiation.getAnArg()) = 1 and Types::getMro(metacls).contains(TType()) - } - or + } or /* Represents `sys.version_info`. Acts like a tuple with a range of values depending on the version being analysed. */ - TSysVersionInfo() - or + TSysVersionInfo() or /* Represents a module that is inferred to perhaps exist, but is not present in the database. */ - TAbsentModule(string name) { - missing_imported_module(_, _, name) - } - or + TAbsentModule(string name) { missing_imported_module(_, _, name) } or /* Represents an attribute of a module that is inferred to perhaps exist, but is not present in the database. */ TAbsentModuleAttribute(AbsentModuleObjectInternal mod, string attrname) { ( PointsToInternal::pointsTo(any(AttrNode attr).getObject(attrname), _, mod, _) or PointsToInternal::pointsTo(any(ImportMemberNode imp).getModule(attrname), _, mod, _) - ) - and + ) and exists(string modname | modname = mod.getName() and not common_module_name(modname + "." + attrname) ) - } - or + } or /* Opaque object representing the result of calling a decorator on a function that we don't understand */ - TDecoratedFunction(CallNode call) { - call.isFunctionDecoratorCall() - } - or + TDecoratedFunction(CallNode call) { call.isFunctionDecoratorCall() } or /* Represents a subscript operation applied to a type. For type-hint analysis */ TSubscriptedType(ObjectInternal generic, ObjectInternal index) { isType(generic) and @@ -252,16 +206,22 @@ predicate isType(ObjectInternal t) { } private predicate is_power_2(int n) { - n = 1 or - exists(int half | is_power_2(half) and n = half*2) + n = 1 + or + exists(int half | is_power_2(half) and n = half * 2) } -predicate static_method(CallNode instantiation, CallableObjectInternal function, PointsToContext context) { - PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::builtin("staticmethod"), _) and +predicate static_method( + CallNode instantiation, CallableObjectInternal function, PointsToContext context +) { + PointsToInternal::pointsTo(instantiation.getFunction(), context, + ObjectInternal::builtin("staticmethod"), _) and PointsToInternal::pointsTo(instantiation.getArg(0), context, function, _) } -predicate class_method(CallNode instantiation, CallableObjectInternal function, PointsToContext context) { +predicate class_method( + CallNode instantiation, CallableObjectInternal function, PointsToContext context +) { PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::classMethod(), _) and PointsToInternal::pointsTo(instantiation.getArg(0), context, function, _) } @@ -285,14 +245,20 @@ predicate literal_instantiation(ControlFlowNode n, ClassObjectInternal cls, Poin ) } -predicate super_instantiation(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) { +predicate super_instantiation( + CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, + PointsToContext context +) { super_2args(instantiation, self, startclass, context) or super_noargs(instantiation, self, startclass, context) } -pragma [noinline] -private predicate super_2args(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) { +pragma[noinline] +private predicate super_2args( + CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, + PointsToContext context +) { exists(ControlFlowNode arg0, ControlFlowNode arg1 | super_call2(instantiation, arg0, arg1, context) and PointsToInternal::pointsTo(arg0, context, startclass, _) and @@ -300,17 +266,23 @@ private predicate super_2args(CallNode instantiation, ObjectInternal self, Class ) } -pragma [noinline] -private predicate super_call2(CallNode call, ControlFlowNode arg0, ControlFlowNode arg1, PointsToContext context) { +pragma[noinline] +private predicate super_call2( + CallNode call, ControlFlowNode arg0, ControlFlowNode arg1, PointsToContext context +) { exists(ControlFlowNode func | call2(call, func, arg0, arg1) and PointsToInternal::pointsTo(func, context, ObjectInternal::superType(), _) ) } -pragma [noinline] -private predicate super_noargs(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) { - PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::builtin("super"), _) and +pragma[noinline] +private predicate super_noargs( + CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, + PointsToContext context +) { + PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::builtin("super"), + _) and not exists(instantiation.getArg(0)) and exists(Function func | instantiation.getScope() = func and @@ -328,7 +300,10 @@ predicate call2(CallNode call, ControlFlowNode func, ControlFlowNode arg0, Contr arg1 = call.getArg(1) } -predicate call3(CallNode call, ControlFlowNode func, ControlFlowNode arg0, ControlFlowNode arg1, ControlFlowNode arg2) { +predicate call3( + CallNode call, ControlFlowNode func, ControlFlowNode arg0, ControlFlowNode arg1, + ControlFlowNode arg2 +) { not exists(call.getArg(3)) and func = call.getFunction() and arg0 = call.getArg(0) and @@ -337,9 +312,11 @@ predicate call3(CallNode call, ControlFlowNode func, ControlFlowNode arg0, Contr } bindingset[self, function] -predicate method_binding(AttrNode instantiation, ObjectInternal self, CallableObjectInternal function, PointsToContext context) { - exists(ObjectInternal obj, string name | - receiver(instantiation, context, obj, name) | +predicate method_binding( + AttrNode instantiation, ObjectInternal self, CallableObjectInternal function, + PointsToContext context +) { + exists(ObjectInternal obj, string name | receiver(instantiation, context, obj, name) | exists(ObjectInternal cls | cls = obj.getClass() and cls != ObjectInternal::superType() and @@ -356,41 +333,45 @@ predicate method_binding(AttrNode instantiation, ObjectInternal self, CallableOb ) } - /** Helper for method_binding */ -pragma [noinline] +pragma[noinline] predicate receiver(AttrNode instantiation, PointsToContext context, ObjectInternal obj, string name) { PointsToInternal::pointsTo(instantiation.getObject(name), context, obj, _) } /** Helper self parameters: `def meth(self, ...): ...`. */ -pragma [noinline] -private predicate self_parameter(ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls) { +pragma[noinline] +private predicate self_parameter( + ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls +) { def.isSelf() and /* Exclude the special parameter name `.0` which is used for unfolded comprehensions. */ def.getName() != ".0" and exists(Function scope | def.getScope() = scope and - context.isRuntime() and context.appliesToScope(scope) and + context.isRuntime() and + context.appliesToScope(scope) and scope.getScope() = cls.getScope() and concrete_class(cls) and - /* We want to allow decorated functions, otherwise we lose a lot of useful information. + /* + * We want to allow decorated functions, otherwise we lose a lot of useful information. * However, we want to exclude any function whose arguments are permuted by the decorator. * In general we can't do that, but we can special case the most common ones. */ + neither_class_nor_static_method(scope) ) } -private cached predicate concrete_class(PythonClassObjectInternal cls) { +cached +private predicate concrete_class(PythonClassObjectInternal cls) { cls.getClass() != abcMetaClassObject() or exists(Class c | c = cls.getScope() and not exists(c.getMetaClass()) - | - forall(Function f | - f.getScope() = c | + | + forall(Function f | f.getScope() = c | not exists(Raise r, Name ex | r.getScope() = f and (r.getException() = ex or r.getException().(Call).getFunc() = ex) and @@ -402,8 +383,7 @@ private cached predicate concrete_class(PythonClassObjectInternal cls) { private PythonClassObjectInternal abcMetaClassObject() { /* Avoid using points-to and thus negative recursion */ - exists(Class abcmeta | - result.getScope() = abcmeta | + exists(Class abcmeta | result.getScope() = abcmeta | abcmeta.getName() = "ABCMeta" and abcmeta.getScope().getName() = "abc" ) @@ -412,19 +392,19 @@ private PythonClassObjectInternal abcMetaClassObject() { private predicate neither_class_nor_static_method(Function f) { not exists(f.getADecorator()) or - exists(ControlFlowNode deco | - deco = f.getADecorator().getAFlowNode() | - exists(ObjectInternal o | - PointsToInternal::pointsTo(deco, _, o, _) | + exists(ControlFlowNode deco | deco = f.getADecorator().getAFlowNode() | + exists(ObjectInternal o | PointsToInternal::pointsTo(deco, _, o, _) | o != ObjectInternal::staticMethod() and o != ObjectInternal::classMethod() ) - or not deco instanceof NameNode + or + not deco instanceof NameNode ) } predicate missing_imported_module(ControlFlowNode imp, Context ctx, string name) { - ctx.isImport() and imp.(ImportExprNode).getNode().getAnImportedModuleName() = name and + ctx.isImport() and + imp.(ImportExprNode).getNode().getAnImportedModuleName() = name and ( not exists(Module m | m.getName() = name) and not exists(Builtin b | b.isModule() and b.getName() = name) @@ -441,41 +421,41 @@ predicate missing_imported_module(ControlFlowNode imp, Context ctx, string name) ) } -/* Helper for missing modules to determine if name `x.y` is a module `x.y` or +/* + * Helper for missing modules to determine if name `x.y` is a module `x.y` or * an attribute `y` of module `x`. This list should be added to as required. */ + predicate common_module_name(string name) { name = "zope.interface" or name = "six.moves" } -/** A declaration of a class, either a built-in class or a source definition +/** + * A declaration of a class, either a built-in class or a source definition * This acts as a helper for ClassObjectInternal allowing some lookup without * recursion. */ library class ClassDecl extends @py_object { - ClassDecl() { this.(Builtin).isClass() and not this = Builtin::unknownType() or this.(ControlFlowNode).getNode() instanceof ClassExpr } - string toString() { - result = "ClassDecl" - } + string toString() { result = "ClassDecl" } /** Gets the class scope for Python class declarations */ - Class getClass() { - result = this.(ControlFlowNode).getNode().(ClassExpr).getInnerScope() - } + Class getClass() { result = this.(ControlFlowNode).getNode().(ClassExpr).getInnerScope() } /** Holds if this class declares the attribute `name` */ predicate declaresAttribute(string name) { exists(this.(Builtin).getMember(name)) or - exists(SsaVariable var | name = var.getId() and var.getAUse() = this.getClass().getANormalExit()) + exists(SsaVariable var | + name = var.getId() and var.getAUse() = this.getClass().getANormalExit() + ) } /** Gets the name of this class */ @@ -485,11 +465,11 @@ library class ClassDecl extends @py_object { result = this.getClass().getName() } - /** Whether this is a class whose instances must be treated specially, rather than as generic instances. + /** + * Whether this is a class whose instances must be treated specially, rather than as generic instances. */ predicate isSpecial() { - exists(string name | - this = Builtin::special(name) | + exists(string name | this = Builtin::special(name) | name = "type" or name = "super" or name = "bool" or @@ -505,16 +485,15 @@ library class ClassDecl extends @py_object { /** Holds if for class `C`, `C()` returns an instance of `C` */ predicate callReturnsInstance() { - exists(Class pycls | - pycls = this.getClass() | + exists(Class pycls | pycls = this.getClass() | /* Django does this, so we need to account for it */ not exists(Function init, LocalVariable self | /* `self.__class__ = ...` in the `__init__` method */ pycls.getInitMethod() = init and - self.isSelf() and self.getScope() = init and + self.isSelf() and + self.getScope() = init and exists(AttrNode a | a.isStore() and a.getObject("__class__") = self.getAUse()) - ) - and + ) and not exists(Function new | new.getName() = "__new__" and new.getScope() = pycls) ) or @@ -527,11 +506,9 @@ library class ClassDecl extends @py_object { m.getName() = "_abcoll" or m.getName() = "_collections_abc" - | + | this.getClass().getScope() = m and this.getName() = name ) } - } - From 4852bb7355dd0acd0c9d9f203b773724b606bd65 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:36:25 +0100 Subject: [PATCH 110/459] Python: Autoformat `pointsto`. --- python/ql/src/semmle/python/pointsto/Base.qll | 158 +- .../src/semmle/python/pointsto/CallGraph.qll | 51 +- .../ql/src/semmle/python/pointsto/Filters.qll | 24 +- .../ql/src/semmle/python/pointsto/Final.qll | 3 +- python/ql/src/semmle/python/pointsto/MRO.qll | 211 +-- .../src/semmle/python/pointsto/Overview.qll | 86 +- .../src/semmle/python/pointsto/PointsTo.qll | 1362 ++++++++++------- .../python/pointsto/PointsToContext.qll | 151 +- 8 files changed, 1165 insertions(+), 881 deletions(-) diff --git a/python/ql/src/semmle/python/pointsto/Base.qll b/python/ql/src/semmle/python/pointsto/Base.qll index 558c60fcc5c..709f1e3d9e3 100644 --- a/python/ql/src/semmle/python/pointsto/Base.qll +++ b/python/ql/src/semmle/python/pointsto/Base.qll @@ -4,22 +4,24 @@ * to the possible objects it points-to the inferred types of those objects and the 'origin' * of those objects. The 'origin' is the point in source code that the object can be traced * back to. - * + * * This file contains non-layered parts of the points-to analysis. */ + import python import semmle.python.essa.SsaDefinitions private import semmle.python.types.Builtins module BasePointsTo { /** INTERNAL -- Use n.refersTo(value, _, origin) instead */ - pragma [noinline] + pragma[noinline] predicate points_to(ControlFlowNode f, Object value, ControlFlowNode origin) { - ( + ( f.isLiteral() and value = f and not f.getNode() instanceof ImmutableLiteral or f.isFunction() and value = f - ) and origin = f + ) and + origin = f } } @@ -35,12 +37,13 @@ predicate varargs_points_to(ControlFlowNode f, ClassObject cls) { cls = theTupleType() } -/** Gets the class of the object for simple cases, namely constants, functions, +/** + * Gets the class of the object for simple cases, namely constants, functions, * comprehensions and built-in objects. * * This exists primarily for internal use. Use getAnInferredType() instead. */ -pragma [noinline] +pragma[noinline] ClassObject simple_types(Object obj) { result = comprehension(obj.getOrigin()) or @@ -79,37 +82,42 @@ private int tuple_index_value(Object t, int i) { result = t.(TupleNode).getElement(i).getNode().(Num).getN().toInt() or exists(Object item | - py_citems(t, i, item) and + py_citems(t, i, item) and result = item.(NumericObject).intValue() ) } -pragma [noinline] +pragma[noinline] int version_tuple_value(Object t) { - not exists(tuple_index_value(t, 1)) and result = tuple_index_value(t, 0)*10 + not exists(tuple_index_value(t, 1)) and result = tuple_index_value(t, 0) * 10 or - not exists(tuple_index_value(t, 2)) and result = tuple_index_value(t, 0)*10 + tuple_index_value(t, 1) + not exists(tuple_index_value(t, 2)) and + result = tuple_index_value(t, 0) * 10 + tuple_index_value(t, 1) or - tuple_index_value(t, 2) = 0 and result = tuple_index_value(t, 0)*10 + tuple_index_value(t, 1) + tuple_index_value(t, 2) = 0 and result = tuple_index_value(t, 0) * 10 + tuple_index_value(t, 1) or - tuple_index_value(t, 2) > 0 and result = tuple_index_value(t, 0)*10 + tuple_index_value(t, 1) + 1 + tuple_index_value(t, 2) > 0 and + result = tuple_index_value(t, 0) * 10 + tuple_index_value(t, 1) + 1 } /** Choose a version numbers that represent the extreme of supported versions. */ private int major_minor() { - if major_version() = 3 then - (result = 33 or result = 37) // 3.3 to 3.7 - else - (result = 25 or result = 27) // 2.5 to 2.7 + if major_version() = 3 + then ( + result = 33 or result = 37 + ) else ( + // 3.3 to 3.7 + result = 25 or result = 27 + ) // 2.5 to 2.7 } /** Compares the given tuple object to both the maximum and minimum possible sys.version_info values */ int version_tuple_compare(Object t) { - version_tuple_value(t) < major_minor() and result = -1 + version_tuple_value(t) < major_minor() and result = -1 or - version_tuple_value(t) = major_minor() and result = 0 + version_tuple_value(t) = major_minor() and result = 0 or - version_tuple_value(t) > major_minor() and result = 1 + version_tuple_value(t) > major_minor() and result = 1 } /* Holds if `cls` is a new-style class if it were to have no explicit base classes */ @@ -121,14 +129,15 @@ predicate baseless_is_new_style(ClassObject cls) { exists(cls.declaredMetaClass()) } -/* The following predicates exist in order to provide +/* + * The following predicates exist in order to provide * more precise type information than the underlying * database relations. This help to optimise the points-to * analysis. */ /** Holds if this class (not on a super-class) declares name */ -pragma [noinline] +pragma[noinline] predicate class_declares_attribute(ClassObject cls, string name) { exists(Class defn | defn = cls.getPyClass() and @@ -136,7 +145,7 @@ predicate class_declares_attribute(ClassObject cls, string name) { ) or exists(Builtin o | - o = cls.asBuiltin().getMember(name) and + o = cls.asBuiltin().getMember(name) and not exists(Builtin sup | sup = cls.asBuiltin().getBaseClass() and o = sup.getMember(name) @@ -151,9 +160,9 @@ private predicate class_defines_name(Class cls, string name) { /** Gets a return value CFG node, provided that is safe to track across returns */ ControlFlowNode safe_return_node(PyFunctionObject func) { - result = func.getAReturnedNode() + result = func.getAReturnedNode() and // Not a parameter - and not exists(Parameter p, SsaVariable pvar | + not exists(Parameter p, SsaVariable pvar | p.asName().getAFlowNode() = pvar.getDefinition() and result = pvar.getAUse() ) and @@ -163,9 +172,11 @@ ControlFlowNode safe_return_node(PyFunctionObject func) { /** Holds if it can be determined from the control flow graph alone that this function can never return */ predicate function_can_never_return(FunctionObject func) { - /* A Python function never returns if it has no normal exits that are not dominated by a + /* + * A Python function never returns if it has no normal exits that are not dominated by a * call to a function which itself never returns. */ + exists(Function f | f = func.getFunction() and not exists(f.getAnExitNode()) @@ -174,27 +185,21 @@ predicate function_can_never_return(FunctionObject func) { func = ModuleObject::named("sys").attr("exit") } - -private newtype TIterationDefinition = +private newtype TIterationDefinition = TIterationDefinition_(SsaSourceVariable var, ControlFlowNode def, ControlFlowNode sequence) { SsaSource::iteration_defined_variable(var, def, sequence) } -/** DEPRECATED. For backwards compatibility only. - * A definition of a variable in a for loop `for v in ...:` */ +/** + * DEPRECATED. For backwards compatibility only. + * A definition of a variable in a for loop `for v in ...:` + */ deprecated class IterationDefinition extends TIterationDefinition { + string toString() { result = "IterationDefinition" } - string toString() { - result = "IterationDefinition" - } - - ControlFlowNode getSequence() { - this = TIterationDefinition_(_, _, result) - } - + ControlFlowNode getSequence() { this = TIterationDefinition_(_, _, result) } } - /** Hold if outer contains inner, both are contained within a test and inner is a use is a plain use or an attribute lookup */ pragma[noinline] predicate contains_interesting_expression_within_test(ControlFlowNode outer, ControlFlowNode inner) { @@ -202,7 +207,8 @@ predicate contains_interesting_expression_within_test(ControlFlowNode outer, Con exists(ControlFlowNode test | outer.getAChild*() = inner and test_contains(test, outer) and - test_contains(test, inner) | + test_contains(test, inner) + | inner instanceof NameNode or inner instanceof AttrNode ) @@ -216,10 +222,14 @@ predicate test_contains(ControlFlowNode expr, ControlFlowNode use) { } /** Holds if `test` is a test (a branch), `use` is within that test and `def` is an edge from that test with `sense` */ -predicate refinement_test(ControlFlowNode test, ControlFlowNode use, boolean sense, PyEdgeRefinement def) { - /* Because calls such as `len` may create a new variable, we need to go via the source variable +predicate refinement_test( + ControlFlowNode test, ControlFlowNode use, boolean sense, PyEdgeRefinement def +) { + /* + * Because calls such as `len` may create a new variable, we need to go via the source variable * That is perfectly safe as we are only dealing with calls that do not mutate their arguments. */ + use = def.getInput().getSourceVariable().(Variable).getAUse() and test = def.getPredecessor().getLastNode() and test_contains(test, use) and @@ -227,11 +237,12 @@ predicate refinement_test(ControlFlowNode test, ControlFlowNode use, boolean sen } /** Holds if `f` is an import of the form `from .[...] import name` and the enclosing scope is an __init__ module */ -pragma [noinline] +pragma[noinline] predicate live_import_from_dot_in_init(ImportMemberNode f, EssaVariable var) { exists(string name | import_from_dot_in_init(f.getModule(name)) and - var.getSourceVariable().getName() = name and var.getAUse() = f + var.getSourceVariable().getName() = name and + var.getAUse() = f ) } @@ -247,23 +258,23 @@ predicate import_from_dot_in_init(ImportExprNode f) { } /** Gets the pseudo-object representing the value referred to by an undefined variable */ -Object undefinedVariable() { - py_special_objects(result, "_semmle_undefined_value") -} +Object undefinedVariable() { py_special_objects(result, "_semmle_undefined_value") } /** Gets the pseudo-object representing an unknown value */ -Object unknownValue() { - result.asBuiltin() = Builtin::unknown() -} +Object unknownValue() { result.asBuiltin() = Builtin::unknown() } BuiltinCallable theTypeNewMethod() { result.asBuiltin() = theTypeType().asBuiltin().getMember("__new__") } /** Gets the `value, cls, origin` that `f` would refer to if it has not been assigned some other value */ -pragma [noinline] -predicate potential_builtin_points_to(NameNode f, Object value, ClassObject cls, ControlFlowNode origin) { - f.isGlobal() and f.isLoad() and origin = f and +pragma[noinline] +predicate potential_builtin_points_to( + NameNode f, Object value, ClassObject cls, ControlFlowNode origin +) { + f.isGlobal() and + f.isLoad() and + origin = f and ( builtin_name_points_to(f.getId(), value, cls) or @@ -271,36 +282,41 @@ predicate potential_builtin_points_to(NameNode f, Object value, ClassObject cls, ) } -pragma [noinline] +pragma[noinline] predicate builtin_name_points_to(string name, Object value, ClassObject cls) { value = Object::builtin(name) and cls.asBuiltin() = value.asBuiltin().getClass() } module BaseFlow { - - predicate reaches_exit(EssaVariable var) { - var.getAUse() = var.getScope().getANormalExit() - } + predicate reaches_exit(EssaVariable var) { var.getAUse() = var.getScope().getANormalExit() } /* Helper for this_scope_entry_value_transfer(...). Transfer of values from earlier scope to later on */ - cached predicate scope_entry_value_transfer_from_earlier(EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope) { + cached + predicate scope_entry_value_transfer_from_earlier( + EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope + ) { exists(SsaSourceVariable var | reaches_exit(pred_var) and pred_var.getScope() = pred_scope and var = pred_var.getSourceVariable() and var = succ_def.getSourceVariable() and succ_def.getScope() = succ_scope - | + | pred_scope.precedes(succ_scope) or - /* If an `__init__` method does not modify the global variable, then + /* + * If an `__init__` method does not modify the global variable, then * we can skip it and take the value directly from the module. */ + exists(Scope init | - init.getName() = "__init__" and init.precedes(succ_scope) and pred_scope.precedes(init) and - not var.(Variable).getAStore().getScope() = init and var instanceof GlobalVariable + init.getName() = "__init__" and + init.precedes(succ_scope) and + pred_scope.precedes(init) and + not var.(Variable).getAStore().getScope() = init and + var instanceof GlobalVariable ) - ) + ) } } @@ -312,15 +328,17 @@ predicate simple_points_to(ControlFlowNode f, Object value, ClassObject cls, Con or BasePointsTo::points_to(f, value, origin) and cls = simple_types(value) or - value = f.getNode().(ImmutableLiteral).getLiteralObject() and cls = simple_types(value) and origin = f + value = f.getNode().(ImmutableLiteral).getLiteralObject() and + cls = simple_types(value) and + origin = f } -/** Holds if `bit` is a binary expression node with a bitwise operator. +/** + * Holds if `bit` is a binary expression node with a bitwise operator. * Helper for `this_binary_expr_points_to`. */ predicate bitwise_expression_node(BinaryExprNode bit, ControlFlowNode left, ControlFlowNode right) { - exists(Operator op | - op = bit.getNode().getOp() | + exists(Operator op | op = bit.getNode().getOp() | op instanceof BitAnd or op instanceof BitOr or op instanceof BitXor @@ -329,16 +347,14 @@ predicate bitwise_expression_node(BinaryExprNode bit, ControlFlowNode left, Cont right = bit.getRight() } - -private -Module theCollectionsAbcModule() { +private Module theCollectionsAbcModule() { result.getName() = "_abcoll" or result.getName() = "_collections_abc" } ClassObject collectionsAbcClass(string name) { - exists(Class cls | + exists(Class cls | result.getPyClass() = cls and cls.getName() = name and cls.getScope() = theCollectionsAbcModule() diff --git a/python/ql/src/semmle/python/pointsto/CallGraph.qll b/python/ql/src/semmle/python/pointsto/CallGraph.qll index cc618690c32..46471238ec2 100644 --- a/python/ql/src/semmle/python/pointsto/CallGraph.qll +++ b/python/ql/src/semmle/python/pointsto/CallGraph.qll @@ -1,42 +1,47 @@ /** * Context-sensitive call-graph. - * + * * NOTE: Since an "invocation" contains callsite information * and a path back to its ancestor calls, the "invocation" call-graph must be a tree. * This has two important consequences: * 1. The graph is incomplete; it has quite limited depth in order to keep the graph to a sensible size. - * 2. The graph is precise. Since different invocations are distinct, there can be no "cross-talk" between + * 2. The graph is precise. Since different invocations are distinct, there can be no "cross-talk" between * different calls to the same function. */ + import python private import semmle.python.pointsto.PointsToContext -private newtype TTInvocation = TInvocation(FunctionObject f, Context c) { - exists(Context outer, CallNode call | - call = f.getACall(outer) and - c.fromCall(call, outer) - ) - or - c.appliesToScope(f.getFunction()) -} +private newtype TTInvocation = + TInvocation(FunctionObject f, Context c) { + exists(Context outer, CallNode call | + call = f.getACall(outer) and + c.fromCall(call, outer) + ) + or + c.appliesToScope(f.getFunction()) + } -/** This class represents a static approximation to the - * dynamic call-graph. A `FunctionInvocation` represents +/** + * This class represents a static approximation to the + * dynamic call-graph. A `FunctionInvocation` represents * all calls made to a function for a given context. */ class FunctionInvocation extends TTInvocation { - string toString() { result = "Invocation" } FunctionObject getFunction() { this = TInvocation(result, _) } Context getContext() { this = TInvocation(_, result) } - /** Gets the callee invocation for the given callsite. + /** + * Gets the callee invocation for the given callsite. * The callsite must be within the function of this invocation. */ FunctionInvocation getCallee(CallNode call) { - exists(FunctionObject callee, Context callee_context, FunctionObject caller, Context caller_context | + exists( + FunctionObject callee, Context callee_context, FunctionObject caller, Context caller_context + | this = TInvocation(caller, caller_context) and result = TInvocation(callee, callee_context) and call = callee.getACall(caller_context) and @@ -45,12 +50,11 @@ class FunctionInvocation extends TTInvocation { ) } - /** Gets a callee invocation. + /** + * Gets a callee invocation. * That is any invocation made from within this invocation. */ - FunctionInvocation getACallee() { - result = this.getCallee(_) - } + FunctionInvocation getACallee() { result = this.getCallee(_) } /** Holds if this is an invocation `f` in the "runtime" context. */ predicate runtime(FunctionObject f) { @@ -61,13 +65,8 @@ class FunctionInvocation extends TTInvocation { } /** Gets the call from which this invocation was made. */ - CallNode getCall() { - this.getContext().fromCall(result, _) - } + CallNode getCall() { this.getContext().fromCall(result, _) } /** Gets the caller invocation of this invocation, if any. */ - FunctionInvocation getCaller() { - this = result.getCallee(_) - } - + FunctionInvocation getCaller() { this = result.getCallee(_) } } diff --git a/python/ql/src/semmle/python/pointsto/Filters.qll b/python/ql/src/semmle/python/pointsto/Filters.qll index 927e6a429de..114711b217c 100644 --- a/python/ql/src/semmle/python/pointsto/Filters.qll +++ b/python/ql/src/semmle/python/pointsto/Filters.qll @@ -1,8 +1,8 @@ -/** Helper predicates for standard tests in Python commonly +/** + * Helper predicates for standard tests in Python commonly * used to filter objects by value or by type. */ - import python /** Holds if `c` is a call to `hasattr(obj, attr)`. */ @@ -21,13 +21,15 @@ predicate is_callable(CallNode c, ControlFlowNode obj) { /** Holds if `c` is a call to `isinstance(use, cls)`. */ predicate isinstance(CallNode fc, ControlFlowNode cls, ControlFlowNode use) { fc.getFunction().(NameNode).getId() = "isinstance" and - cls = fc.getArg(1) and fc.getArg(0) = use + cls = fc.getArg(1) and + fc.getArg(0) = use } /** Holds if `c` is a call to `issubclass(use, cls)`. */ predicate issubclass(CallNode fc, ControlFlowNode cls, ControlFlowNode use) { fc.getFunction().(NameNode).getId() = "issubclass" and - fc.getArg(0) = use and cls = fc.getArg(1) + fc.getArg(0) = use and + cls = fc.getArg(1) } /** Holds if `c` is a test comparing `x` and `y`. `is` is true if the operator is `is` or `==`, it is false if the operator is `is not` or `!=`. */ @@ -35,11 +37,15 @@ predicate equality_test(CompareNode c, ControlFlowNode x, boolean is, ControlFlo exists(Cmpop op | c.operands(x, op, y) or c.operands(y, op, x) - | - (is = true and op instanceof Is or - is = false and op instanceof IsNot or - is = true and op instanceof Eq or - is = false and op instanceof NotEq + | + ( + is = true and op instanceof Is + or + is = false and op instanceof IsNot + or + is = true and op instanceof Eq + or + is = false and op instanceof NotEq ) ) } diff --git a/python/ql/src/semmle/python/pointsto/Final.qll b/python/ql/src/semmle/python/pointsto/Final.qll index a1f14b0f87c..b02c42852a1 100644 --- a/python/ql/src/semmle/python/pointsto/Final.qll +++ b/python/ql/src/semmle/python/pointsto/Final.qll @@ -1,6 +1,5 @@ /* For backwards compatibility */ - import PointsTo::PointsTo as P /** DEPRECATED: Use `PointsTo` instead */ -deprecated module FinalPointsTo = P; \ No newline at end of file +deprecated module FinalPointsTo = P; diff --git a/python/ql/src/semmle/python/pointsto/MRO.qll b/python/ql/src/semmle/python/pointsto/MRO.qll index 98e8eea9bbd..cc159ecbb0f 100644 --- a/python/ql/src/semmle/python/pointsto/MRO.qll +++ b/python/ql/src/semmle/python/pointsto/MRO.qll @@ -1,4 +1,5 @@ -/** Classes and predicates for computing the Method Resolution Order (MRO) of classes. +/** + * Classes and predicates for computing the Method Resolution Order (MRO) of classes. * Supports both old-style (diamond) inheritance and new-style (C3 linearization) inheritance. */ @@ -17,19 +18,16 @@ */ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext private import semmle.python.types.Builtins - -cached newtype TClassList = Empty() - or - Cons(ClassObjectInternal head, TClassList tail) { - required_cons(head, tail) - } +cached +newtype TClassList = + Empty() or + Cons(ClassObjectInternal head, TClassList tail) { required_cons(head, tail) } /* Keep ClassList finite and as small as possible */ private predicate required_cons(ClassObjectInternal head, ClassList tail) { @@ -38,7 +36,7 @@ private predicate required_cons(ClassObjectInternal head, ClassList tail) { tail = merge_of_linearization_of_bases(head) or exists(ClassObjectInternal cls, int n | - head = Types::getBase(cls, n) and tail = bases(cls, n+1) + head = Types::getBase(cls, n) and tail = bases(cls, n + 1) ) or head = ObjectInternal::builtin("object") and tail = Empty() @@ -52,12 +50,12 @@ private predicate required_cons(ClassObjectInternal head, ClassList tail) { or exists(ClassList list, int n | n = list.firstIndex(head) and - tail = list.deduplicate(n+1) + tail = list.deduplicate(n + 1) ) or exists(ClassListList list, int n | head = list.getHead().getItem(n) and - tail = flatten_list(list, n+1) + tail = flatten_list(list, n + 1) ) or tail = list_old_style_base_mros(head).flatten() @@ -70,16 +68,12 @@ private ClassObjectInternal sole_base(ClassObjectInternal cls) { /** A list of classes, used to represent the MRO of a class */ class ClassList extends TClassList { - - string toString() { - result = "[" + this.contents() + "]" - } + string toString() { result = "[" + this.contents() + "]" } string contents() { this = Empty() and result = "" or - exists(ClassObjectInternal head | - head = this.getHead() | + exists(ClassObjectInternal head | head = this.getHead() | this.getTail() = Empty() and result = className(head) or this.getTail() != Empty() and result = className(head) + ", " + this.getTail().contents() @@ -98,25 +92,19 @@ class ClassList extends TClassList { result = this.getTail().length() + 1 } - ClassObjectInternal getHead() { - this = Cons(result, _) - } + ClassObjectInternal getHead() { this = Cons(result, _) } - ClassList getTail() { - this = Cons(_, result) - } + ClassList getTail() { this = Cons(_, result) } ClassObjectInternal getItem(int n) { - n = 0 and result = this.getHead() + n = 0 and result = this.getHead() or - result = this.getTail().getItem(n-1) + result = this.getTail().getItem(n - 1) } - ClassObjectInternal getAnItem() { - result = this.getItem(_) - } + ClassObjectInternal getAnItem() { result = this.getItem(_) } - pragma [inline] + pragma[inline] ClassList removeHead(ClassObjectInternal cls) { this.getHead() = cls and result = this.getTail() or @@ -159,18 +147,15 @@ class ClassList extends TClassList { } ClassObjectInternal findDeclaringClass(string name) { - exists(ClassDecl head | - head = this.getHead().getClassDeclaration() | - if head.declaresAttribute(name) then - result = this.getHead() - else - result = this.getTail().findDeclaringClass(name) + exists(ClassDecl head | head = this.getHead().getClassDeclaration() | + if head.declaresAttribute(name) + then result = this.getHead() + else result = this.getTail().findDeclaringClass(name) ) } predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - exists(ClassObjectInternal decl | - decl = this.findDeclaringClass(name) | + exists(ClassObjectInternal decl | decl = this.findDeclaringClass(name) | Types::declaredAttribute(decl, name, value, origin) ) } @@ -182,83 +167,63 @@ class ClassList extends TClassList { } ClassList startingAt(ClassObjectInternal cls) { - exists(ClassObjectInternal head | - head = this.getHead() | - if head = cls then - result = this - else - result = this.getTail().startingAt(cls) + exists(ClassObjectInternal head | head = this.getHead() | + if head = cls then result = this else result = this.getTail().startingAt(cls) ) } - ClassList deduplicate() { - result = this.deduplicate(0) - } + ClassList deduplicate() { result = this.deduplicate(0) } /* Helpers for `deduplicate()` */ - - int firstIndex(ClassObjectInternal cls) { - result = this.firstIndex(cls, 0) - } + int firstIndex(ClassObjectInternal cls) { result = this.firstIndex(cls, 0) } /* Helper for firstIndex(cls), getting the first index of `cls` where result >= n */ private int firstIndex(ClassObjectInternal cls, int n) { this.getItem(n) = cls and result = n or - this.getItem(n) != cls and result = this.firstIndex(cls, n+1) + this.getItem(n) != cls and result = this.firstIndex(cls, n + 1) } /** Holds if the class at `n` is a duplicate of an earlier position. */ private predicate duplicate(int n) { - exists(ClassObjectInternal cls | - cls = this.getItem(n) and this.firstIndex(cls) < n - ) + exists(ClassObjectInternal cls | cls = this.getItem(n) and this.firstIndex(cls) < n) } - /** Gets a class list which is the de-duplicated form of the list containing elements of + /** + * Gets a class list which is the de-duplicated form of the list containing elements of * this list from `n` onwards. */ ClassList deduplicate(int n) { n = this.length() and result = Empty() or - this.duplicate(n) and result = this.deduplicate(n+1) + this.duplicate(n) and result = this.deduplicate(n + 1) or exists(ClassObjectInternal cls | n = this.firstIndex(cls) and - result = Cons(cls, this.deduplicate(n+1)) + result = Cons(cls, this.deduplicate(n + 1)) ) } - predicate isEmpty() { - this = Empty() - } + predicate isEmpty() { this = Empty() } - ClassList reverse() { - reverse_step(this, Empty(), result) - } + ClassList reverse() { reverse_step(this, Empty(), result) } - /** Holds if this MRO contains a class whose instances we treat specially, rather than as a generic instance. + /** + * Holds if this MRO contains a class whose instances we treat specially, rather than as a generic instance. * For example, `type` or `int`. */ boolean containsSpecial() { this = Empty() and result = false or - exists(ClassDecl decl | - decl = this.getHead().getClassDeclaration() | - if decl.isSpecial() then - result = true - else - result = this.getTail().containsSpecial() + exists(ClassDecl decl | decl = this.getHead().getClassDeclaration() | + if decl.isSpecial() then result = true else result = this.getTail().containsSpecial() ) } - } private newtype TClassListList = EmptyList() or - ConsList(TClassList head, TClassListList tail) { - required_list(head, tail) - } + ConsList(TClassList head, TClassListList tail) { required_list(head, tail) } /* Keep ClassListList finite and as small as possible */ private predicate required_list(ClassList head, ClassListList tail) { @@ -268,26 +233,22 @@ private predicate required_list(ClassList head, ClassListList tail) { or exists(ClassObjectInternal cls, int n | head = Mro::newStyleMro(Types::getBase(cls, n)) and - tail = list_of_linearization_of_bases_plus_bases(cls, n+1) + tail = list_of_linearization_of_bases_plus_bases(cls, n + 1) ) or exists(ClassObjectInternal cls, int n | head = Mro::oldStyleMro(Types::getBase(cls, n)) and - tail = list_old_style_base_mros(cls, n+1) + tail = list_old_style_base_mros(cls, n + 1) ) } private class ClassListList extends TClassListList { - - string toString() { - result = "[" + this.contents() + "]" - } + string toString() { result = "[" + this.contents() + "]" } string contents() { this = EmptyList() and result = "" or - exists(ClassList head | - head = this.getHead() | + exists(ClassList head | head = this.getHead() | this.getTail() = EmptyList() and result = head.toString() or this.getTail() != EmptyList() and result = head.toString() + ", " + this.getTail().contents() @@ -300,18 +261,14 @@ private class ClassListList extends TClassListList { result = this.getTail().length() + 1 } - ClassList getHead() { - this = ConsList(result, _) - } + ClassList getHead() { this = ConsList(result, _) } - ClassListList getTail() { - this = ConsList(_, result) - } + ClassListList getTail() { this = ConsList(_, result) } ClassList getItem(int n) { n = 0 and result = this.getHead() or - result = this.getTail().getItem(n-1) + result = this.getTail().getItem(n - 1) } private ClassObjectInternal getAHead() { @@ -320,7 +277,7 @@ private class ClassListList extends TClassListList { result = this.getTail().getAHead() } - pragma [nomagic] + pragma[nomagic] ClassList merge() { exists(ClassList reversed | merge_step(reversed, EmptyList(), this) and @@ -331,13 +288,17 @@ private class ClassListList extends TClassListList { } /* Join ordering helper */ - pragma [noinline] - predicate removedClassParts(ClassObjectInternal cls, ClassList removed_head, ClassListList removed_tail, int n) { - cls = this.bestMergeCandidate() and n = this.length()-1 and - removed_head = this.getItem(n).removeHead(cls) and removed_tail = EmptyList() + pragma[noinline] + predicate removedClassParts( + ClassObjectInternal cls, ClassList removed_head, ClassListList removed_tail, int n + ) { + cls = this.bestMergeCandidate() and + n = this.length() - 1 and + removed_head = this.getItem(n).removeHead(cls) and + removed_tail = EmptyList() or exists(ClassList prev_head, ClassListList prev_tail | - this.removedClassParts(cls, prev_head, prev_tail, n+1) and + this.removedClassParts(cls, prev_head, prev_tail, n + 1) and removed_head = this.getItem(n).removeHead(cls) and removed_tail = ConsList(prev_head, prev_tail) ) @@ -356,12 +317,10 @@ private class ClassListList extends TClassListList { cls = this.getAHead() and n = this.length() or this.getItem(n).legalMergeHead(cls) and - this.legalMergeCandidate(cls, n+1) + this.legalMergeCandidate(cls, n + 1) } - predicate legalMergeCandidate(ClassObjectInternal cls) { - this.legalMergeCandidate(cls, 0) - } + predicate legalMergeCandidate(ClassObjectInternal cls) { this.legalMergeCandidate(cls, 0) } predicate illegalMergeCandidate(ClassObjectInternal cls) { cls = this.getAHead() and @@ -369,20 +328,17 @@ private class ClassListList extends TClassListList { } ClassObjectInternal bestMergeCandidate(int n) { - exists(ClassObjectInternal head | - head = this.getItem(n).getHead() - | + exists(ClassObjectInternal head | head = this.getItem(n).getHead() | legalMergeCandidate(head) and result = head or - illegalMergeCandidate(head) and result = this.bestMergeCandidate(n+1) + illegalMergeCandidate(head) and result = this.bestMergeCandidate(n + 1) ) } - ClassObjectInternal bestMergeCandidate() { - result = this.bestMergeCandidate(0) - } + ClassObjectInternal bestMergeCandidate() { result = this.bestMergeCandidate(0) } - /** Gets a ClassList representing the this list of list flattened into a single list. + /** + * Gets a ClassList representing the this list of list flattened into a single list. * Used for old-style MRO computation. */ ClassList flatten() { @@ -390,17 +346,14 @@ private class ClassListList extends TClassListList { or result = flatten_list(this, 0) } - } private ClassList flatten_list(ClassListList list, int n) { need_flattening(list) and - exists(ClassList head, ClassListList tail | - list = ConsList(head, tail) - | + exists(ClassList head, ClassListList tail | list = ConsList(head, tail) | n = head.length() and result = tail.flatten() or - result = Cons(head.getItem(n), flatten_list(list, n+1)) + result = Cons(head.getItem(n), flatten_list(list, n + 1)) ) } @@ -414,12 +367,10 @@ private predicate need_flattening(ClassListList list) { ) } -private ClassList bases(ClassObjectInternal cls) { - result = bases(cls, 0) -} +private ClassList bases(ClassObjectInternal cls) { result = bases(cls, 0) } private ClassList bases(ClassObjectInternal cls, int n) { - result = Cons(Types::getBase(cls, n), bases(cls, n+1)) + result = Cons(Types::getBase(cls, n), bases(cls, n + 1)) or result = Empty() and n = Types::base_count(cls) } @@ -432,7 +383,7 @@ private ClassListList list_of_linearization_of_bases_plus_bases(ClassObjectInter result = ConsList(bases(cls), EmptyList()) and n = Types::base_count(cls) and n > 1 or exists(ClassListList partial | - partial = list_of_linearization_of_bases_plus_bases(cls, n+1) and + partial = list_of_linearization_of_bases_plus_bases(cls, n + 1) and result = ConsList(Mro::newStyleMro(Types::getBase(cls, n)), partial) ) } @@ -445,18 +396,23 @@ private ClassListList list_old_style_base_mros(ClassObjectInternal cls) { result = list_old_style_base_mros(cls, 0) } -pragma [nomagic] +pragma[nomagic] private ClassListList list_old_style_base_mros(ClassObjectInternal cls, int n) { n = Types::base_count(cls) and result = EmptyList() or - result = ConsList(Mro::oldStyleMro(Types::getBase(cls, n)), list_old_style_base_mros(cls, n+1)) + result = ConsList(Mro::oldStyleMro(Types::getBase(cls, n)), list_old_style_base_mros(cls, n + 1)) } -/** Holds if the pair `reversed_mro`, `remaining_list` represents a step in the C3 merge operation +/** + * Holds if the pair `reversed_mro`, `remaining_list` represents a step in the C3 merge operation * of computing the C3 linearization of `original`. */ -private predicate merge_step(ClassList reversed_mro, ClassListList remaining_list, ClassListList original) { - remaining_list = list_of_linearization_of_bases_plus_bases(_) and reversed_mro = Empty() and remaining_list = original +private predicate merge_step( + ClassList reversed_mro, ClassListList remaining_list, ClassListList original +) { + remaining_list = list_of_linearization_of_bases_plus_bases(_) and + reversed_mro = Empty() and + remaining_list = original or /* Removes the best merge candidate from `remaining_list` and prepends it to `reversed_mro` */ exists(ClassObjectInternal head, ClassList prev_reverse_mro, ClassListList prev_list | @@ -470,7 +426,6 @@ private predicate merge_step(ClassList reversed_mro, ClassListList remaining_lis } /* Helpers for `ClassList.reverse()` */ - private predicate needs_reversing(ClassList lst) { merge_step(lst, EmptyList(), _) or @@ -487,8 +442,8 @@ private predicate reverse_step(ClassList lst, ClassList remainder, ClassList rev } module Mro { - - cached ClassList newStyleMro(ClassObjectInternal cls) { + cached + ClassList newStyleMro(ClassObjectInternal cls) { cls = ObjectInternal::builtin("object") and result = Cons(cls, Empty()) or result = Cons(cls, merge_of_linearization_of_bases(cls)) @@ -496,9 +451,9 @@ module Mro { result = Cons(cls, newStyleMro(sole_base(cls))) } - cached ClassList oldStyleMro(ClassObjectInternal cls) { + cached + ClassList oldStyleMro(ClassObjectInternal cls) { Types::isOldStyle(cls) and result = Cons(cls, list_old_style_base_mros(cls).flatten()).(ClassList).deduplicate() } - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/pointsto/Overview.qll b/python/ql/src/semmle/python/pointsto/Overview.qll index aae2e04f018..7e343f8934a 100644 --- a/python/ql/src/semmle/python/pointsto/Overview.qll +++ b/python/ql/src/semmle/python/pointsto/Overview.qll @@ -1,45 +1,45 @@ + /* - * * ## Points-to analysis for Python - * - * + * + * * The purpose of points-to analysis is to determine what values a variable might hold at runtime. * This allows us to write useful queries to check for the misuse of those values. * In the academic and technical literature, points-to analysis (AKA pointer analysis) attempts to determine which variables can refer to which heap allocated objects. * From the point of view of Python we can treat all Python objects as "heap allocated objects". - * - * + * + * * The output of the points-to analysis consists of a large set of relations which provide not only points-to information, but call-graph, pruned flow-graph and exception-raising information. - * - * These relations are computed by a large set of mutually recursive predicates which infer the flow of values through the program. + * + * These relations are computed by a large set of mutually recursive predicates which infer the flow of values through the program. * Our analysis is inter-procedural use contexts to maintain the precision of an intra-procedural analysis. - * + * * ### Precision - * + * * In conventional points-to, the computed points-to set should be a super-set of the real points-to set (were it possible to determine such a thing). - * However for our purposes we want the points-to set to be a sub-set of the real points-to set. - * This is simply because conventional points-to is used to determine compiler optimisations, so the points-to set needs to be a conservative over-estimate of what is possible. + * However for our purposes we want the points-to set to be a sub-set of the real points-to set. + * This is simply because conventional points-to is used to determine compiler optimisations, so the points-to set needs to be a conservative over-estimate of what is possible. * We have the opposite concern; we want to eliminate false positives where possible. - * - * This should be born in mind when reading the literature about points-to analysis. In conventional points-to, a precise analysis produces as small a points-to set as possible. + * + * This should be born in mind when reading the literature about points-to analysis. In conventional points-to, a precise analysis produces as small a points-to set as possible. * Our analysis is precise (or very close to it). Instead of seeking to maximise precision, we seek to maximise *recall* and produce as large a points-to set as possible (whilst remaining precise). - * + * * When it comes to designing the inference, we always choose precision over recall. * We want to minimise false positives so it is important to avoid making incorrect inferences, even if it means losing a lot of potential information. * If a potential new points-to fact would increase the number of values we are able to infer, but decrease precision, then we omit it. - * + * * ###Objects - * - * In convention points-to an 'object' is generally considered to be any static instantiation. E.g. in Java this is simply anything looking like `new X(..)`. - * However, in Python as there is no `new` expression we cannot known what is a class merely from the syntax. + * + * In convention points-to an 'object' is generally considered to be any static instantiation. E.g. in Java this is simply anything looking like `new X(..)`. + * However, in Python as there is no `new` expression we cannot known what is a class merely from the syntax. * Consequently, we must start with only with the simplest objects and extend to instance creation as we can infer classes. - * + * * To perform points-to analysis we start with the set of built-in objects, all literal constants, and class and function definitions. * From there we can propagate those values. Whenever we see a call `x()` we add a new object if `x` refers to some class. - * + * * In the `PointsTo::points_to` relation, the second argument, `Object value` is the "value" referred to by the ControlFlowNode (which will correspond to an rvalue in the source code). * The set of "values" used will change as the library continues to improve, but currently include the following: - * + * * * Classes (both in the source and builtin) * * Functions (both in the source and builtin) * * Literal constants defined in the source (string and numbers) @@ -49,56 +49,56 @@ * * Bound methods, static- and class-methods, and properties. * * Instances of `super`. * * Missing modules, where no concrete module is found for an import. - * + * * A number of constructs that might create a new object, such as binary operations, are omitted if there is no useful information to can be attached to them and they would just increase the size of the database. - * + * * ###Contexts - * - * In order to better handle value tracking in functions, we introduce context to the points-to relation. + * + * In order to better handle value tracking in functions, we introduce context to the points-to relation. * There is one `default` context, equivalent to having no context, a `main` context for scripts and any number of call-site contexts. - * - * Adding context to a conventional points-to analysis can significantly improve its precision. Whereas, for our points-to analysis adding context significantly improves the recall of our analysis. - * The consensus in the academic literature is that "object sensitivity" is superior to "call-site sensitivity". + * + * Adding context to a conventional points-to analysis can significantly improve its precision. Whereas, for our points-to analysis adding context significantly improves the recall of our analysis. + * The consensus in the academic literature is that "object sensitivity" is superior to "call-site sensitivity". * However, since we are seeking to maximise not minimise our points-to set, it is entirely possible that the reverse is true for us. * We use "call-site sensitivity" at the moment, although the exact set of contexts used will change. - * + * * ### Points-to analysis over the ESSA dataflow graph - * + * * In order to perform points-to analysis on the dataflow graph, we * need to understand the many implicit "definitions" that occur within Python code. - * + * * These are: - * + * * 1. Implicit definition as "undefined" for any local or global variable at the start of its scope. * Many of these will be dead and will be eliminated during construction of the dataflow graph. * 2. Implicit definition of `__name__`, `__package__` and `__module__` at the start of the relevant scopes. * 3. Implicit definition of all submodules as global variables at the start of an `__init__` module - * + * * In addition, there are the "artificial", data-flow definitions: - * + * * 1. Phi functions * 2. Pi (guard, or filter) functions. * 3. "Refinements" of a variable. These are not definitions of the variable, but may modify the object referred to by the variable, * possibly changing some inferred facts about the object. * 4. Definition of any variable that escapes the scope, at entry, exit and at all call-sites. - * + * * As an example, consider: * ```python * if a: * float = "global" * #float can now be either the class 'float' or the string "global" - * + * * class C2: * if b: * float = "local" * float - * + * * float #Cannot be "local" * ``` - * + * * Ignoring `__name__` and `__package__`, the data-flow graph looks something like this, noting that there are two variables named "float" * in the scope `C2`, the local and the global. - * + * * ``` * a_0 = undefined * b_0 = undefined @@ -112,14 +112,14 @@ * float_6 = phi(float_4, float_5) | * float_7 = float_3 (transfer values in global 'float', but not local, back to module scope). * ``` - * + * * ### Implementation - * + * * This section is for information purposes only. Any or all details may change without notice. - * + * * QL, being based on Datalog, has fixed-point semantics which makes it impossible to make negative statements that are recursive. * To work around this we need to define many predicates over boolean variables. Suppose we have a predicate with determines whether a test can be true or false at runtime. * We might naively implement this as `predicate test_is_true(ControlFlowNode test, Context ctx)` but this would lead to negative recursion if we want to know when the test can be false. * Instead we implement it as `boolean test_result(ControlFlowNode test, Context ctx)` where the absence of a value indicates merely that we do (yet) know what value the test may have. - * */ + diff --git a/python/ql/src/semmle/python/pointsto/PointsTo.qll b/python/ql/src/semmle/python/pointsto/PointsTo.qll index cdfcceb2c8b..9bcead16c13 100644 --- a/python/ql/src/semmle/python/pointsto/PointsTo.qll +++ b/python/ql/src/semmle/python/pointsto/PointsTo.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.Filters @@ -10,13 +9,13 @@ private import semmle.python.types.Extensions /* Use this version for speed */ library class CfgOrigin extends @py_object { - string toString() { /* Not to be displayed */ result = "CfgOrigin" } - /** Get a `ControlFlowNode` from `this` or `here`. + /** + * Get a `ControlFlowNode` from `this` or `here`. * If `this` is a ControlFlowNode then use that, otherwise fall back on `here` */ pragma[inline] @@ -26,36 +25,24 @@ library class CfgOrigin extends @py_object { not this instanceof ControlFlowNode and result = here } - ControlFlowNode toCfgNode() { - result = this - } + ControlFlowNode toCfgNode() { result = this } pragma[inline] CfgOrigin fix(ControlFlowNode here) { - if this = Builtin::unknown() then - result = here - else - result = this + if this = Builtin::unknown() then result = here else result = this } - } module CfgOrigin { + CfgOrigin fromCfgNode(ControlFlowNode f) { result = f } - CfgOrigin fromCfgNode(ControlFlowNode f) { - result = f - } - - CfgOrigin unknown() { - result = Builtin::unknown() - } + CfgOrigin unknown() { result = Builtin::unknown() } CfgOrigin fromObject(ObjectInternal obj) { obj.isBuiltin() and result = unknown() or result = obj.getOrigin() } - } /* Use this version for stronger type-checking */ @@ -111,88 +98,104 @@ module CfgOrigin { // } // //} - /* The API */ module PointsTo { - - predicate pointsTo(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + predicate pointsTo( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { PointsToInternal::pointsTo(f, context, value, origin) } - predicate variablePointsTo(EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + predicate variablePointsTo( + EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { PointsToInternal::variablePointsTo(var, context, value, origin) } /* Backwards compatibility */ - deprecated cached predicate - points_to(ControlFlowNode f, PointsToContext context, Object obj, ClassObject cls, ControlFlowNode origin) { + cached + deprecated predicate points_to( + ControlFlowNode f, PointsToContext context, Object obj, ClassObject cls, ControlFlowNode origin + ) { exists(ObjectInternal value | PointsToInternal::pointsTo(f, context, value, origin) and - cls = value.getClass().getSource() | - obj = value.getSource() or + cls = value.getClass().getSource() + | + obj = value.getSource() + or value.useOriginAsLegacyObject() and obj = origin ) or /* Backwards compatibility for *args and **kwargs */ - exists(Function func | - obj = f and origin = f and context.isRuntime() | - func.getVararg() = f.getNode() and cls = theTupleType() or + exists(Function func | obj = f and origin = f and context.isRuntime() | + func.getVararg() = f.getNode() and cls = theTupleType() + or func.getKwarg() = f.getNode() and cls = theDictType() ) or not f.isParameter() and exists(ObjectInternal value | PointsToInternal::pointsTo(f.(DefinitionNode).getValue(), context, value, origin) and - cls = value.getClass().getSource() | - obj = value.getSource() or + cls = value.getClass().getSource() + | + obj = value.getSource() + or value.useOriginAsLegacyObject() and obj = origin ) } - deprecated predicate - ssa_variable_points_to(EssaVariable var, PointsToContext context, Object obj, ClassObject cls, CfgOrigin origin) { + deprecated predicate ssa_variable_points_to( + EssaVariable var, PointsToContext context, Object obj, ClassObject cls, CfgOrigin origin + ) { exists(ObjectInternal value | PointsToInternal::variablePointsTo(var, context, value, origin) and - cls = value.getClass().getSource() | + cls = value.getClass().getSource() + | obj = value.getSource() ) } - deprecated - CallNode get_a_call(Object func, PointsToContext context) { + deprecated CallNode get_a_call(Object func, PointsToContext context) { exists(ObjectInternal value | result = value.(Value).getACall(context) and func = value.getSource() ) } - cached predicate moduleExports(ModuleObjectInternal mod, string name) { + cached + predicate moduleExports(ModuleObjectInternal mod, string name) { InterModulePointsTo::moduleExportsBoolean(mod, name) = true } - } -cached module PointsToInternal { - +cached +module PointsToInternal { pragma[noinline] - cached predicate importCtxPointsTo(ControlFlowNode f, ObjectInternal value, ControlFlowNode origin) { - PointsToInternal::pointsTo(f, any(Context ctx | ctx.isImport()), value, origin) + cached + predicate importCtxPointsTo(ControlFlowNode f, ObjectInternal value, ControlFlowNode origin) { + PointsToInternal::pointsTo(f, any(Context ctx | ctx.isImport()), value, origin) } /** INTERNAL -- Use `f.refersTo(value, origin)` instead. */ - cached predicate pointsTo(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + cached + predicate pointsTo( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { points_to_candidate(f, context, value, origin) and reachableBlock(f.getBasicBlock(), context) } - cached predicate pointsToString(ControlFlowNode f, PointsToContext context, string value) { + cached + predicate pointsToString(ControlFlowNode f, PointsToContext context, string value) { exists(ObjectInternal str | PointsToInternal::pointsTo(f, context, str, _) and str.strValue() = value ) } - private predicate points_to_candidate(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate points_to_candidate( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { use_points_to(f, context, value, origin) or attribute_load_points_to(f, context, value, origin) @@ -216,18 +219,21 @@ cached module PointsToInternal { iteration_points_to(f, context, value, origin) } - /** Holds if the attribute `name` is required for `obj` + /** + * Holds if the attribute `name` is required for `obj` * For object `x` and attribute `name` it means that there exists somewhere in the code * `x.name` or `getattr(x, "name")`. */ - cached predicate attributeRequired(ObjectInternal obj, string name) { + cached + predicate attributeRequired(ObjectInternal obj, string name) { pointsTo(any(AttrNode a).getObject(name), _, obj, _) or Expressions::getattr_call(_, _, _, obj, name) } /* Holds if BasicBlock `b` is reachable, given the context `context`. */ - cached predicate reachableBlock(BasicBlock b, PointsToContext context) { + cached + predicate reachableBlock(BasicBlock b, PointsToContext context) { exists(Scope scope | context.appliesToScope(scope) and scope.getEntryNode().getBasicBlock() = b @@ -250,7 +256,7 @@ cached module PointsToInternal { test = pred.getLastNode() and pointsTo(test, context, value, _) and sense = value.booleanValue() - | + | sense = true and succ = pred.getATrueSuccessor() or sense = false and succ = pred.getAFalseSuccessor() @@ -259,28 +265,37 @@ cached module PointsToInternal { } /** Gets an object pointed to by a use (of a variable). */ - pragma [noinline] - private predicate use_points_to(NameNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate use_points_to( + NameNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(CfgOrigin origin_or_obj | value != ObjectInternal::undefined() and - use_points_to_maybe_origin(f, context, value, origin_or_obj) | + use_points_to_maybe_origin(f, context, value, origin_or_obj) + | origin = origin_or_obj.asCfgNodeOrHere(f) ) } - pragma [noinline] - private predicate use_points_to_maybe_origin(NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj) { - variablePointsTo(fast_local_variable(f), context, value, origin_or_obj) + pragma[noinline] + private predicate use_points_to_maybe_origin( + NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj + ) { + variablePointsTo(fast_local_variable(f), context, value, origin_or_obj) or name_lookup_points_to_maybe_origin(f, context, value, origin_or_obj) or - not exists(fast_local_variable(f)) and not exists(name_local_variable(f)) and + not exists(fast_local_variable(f)) and + not exists(name_local_variable(f)) and global_lookup_points_to_maybe_origin(f, context, value, origin_or_obj) } /** Holds if `var` refers to `(value, origin)` given the context `context`. */ - pragma [noinline] - cached predicate variablePointsTo(EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + cached + predicate variablePointsTo( + EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { ssa_definition_points_to(var.getDefinition(), context, value, origin) or exists(EssaVariable prev | @@ -299,16 +314,21 @@ cached module PointsToInternal { end.getDefinition() = def ) or - /* Ignore the effects of calls on their arguments. PointsTo is an approximation, - * but attempting to improve accuracy would be very expensive for very little gain. */ + /* + * Ignore the effects of calls on their arguments. PointsTo is an approximation, + * but attempting to improve accuracy would be very expensive for very little gain. + */ + exists(ArgumentRefinement def | start = def.getInput() and end.getDefinition() = def ) } - pragma [noinline] - private predicate name_lookup_points_to_maybe_origin(NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj) { + pragma[noinline] + private predicate name_lookup_points_to_maybe_origin( + NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj + ) { exists(EssaVariable var | var = name_local_variable(f) | variablePointsTo(var, context, value, origin_or_obj) ) @@ -317,22 +337,23 @@ cached module PointsToInternal { global_lookup_points_to_maybe_origin(f, context, value, origin_or_obj) } - pragma [noinline] + pragma[noinline] private predicate local_variable_undefined(NameNode f, PointsToContext context) { variablePointsTo(name_local_variable(f), context, ObjectInternal::undefined(), _) } - pragma [noinline] - private predicate global_lookup_points_to_maybe_origin(NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj) { + pragma[noinline] + private predicate global_lookup_points_to_maybe_origin( + NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj + ) { variablePointsTo(global_variable(f), context, value, origin_or_obj) or - exists(ControlFlowNode origin | - origin_or_obj = CfgOrigin::fromCfgNode(origin) - | + exists(ControlFlowNode origin | origin_or_obj = CfgOrigin::fromCfgNode(origin) | variablePointsTo(global_variable(f), context, ObjectInternal::undefined(), _) and potential_builtin_points_to(f, value, origin) or - not exists(global_variable(f)) and context.appliesToScope(f.getScope()) and + not exists(global_variable(f)) and + context.appliesToScope(f.getScope()) and potential_builtin_points_to(f, value, origin) ) } @@ -359,8 +380,10 @@ cached module PointsToInternal { } /** Holds if `f` is an attribute `x.attr` and points to `(value, cls, origin)`. */ - pragma [noinline] - private predicate attribute_load_points_to(AttrNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate attribute_load_points_to( + AttrNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { none() // TO DO -- Support CustomPointsToAttribute //or @@ -370,12 +393,16 @@ cached module PointsToInternal { //) } - /* Treat `ForNode` as intermediate step between sequence and iteration variable. + /* + * Treat `ForNode` as intermediate step between sequence and iteration variable. * In otherwords treat `for i in x:` as being equivalent to `i = next(iter(x))` * attaching the value of `next(iter(x))` to the `ForNode`. */ - pragma [noinline] - private predicate iteration_points_to(ForNode for, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + + pragma[noinline] + private predicate iteration_points_to( + ForNode for, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(ControlFlowNode seqNode, ObjectInternal seq | for.iterates(_, seqNode) and pointsTo(seqNode, context, seq, _) and @@ -385,7 +412,9 @@ cached module PointsToInternal { } /** Holds if the ESSA definition `def` refers to `(value, origin)` given the context `context`. */ - private predicate ssa_definition_points_to(EssaDefinition def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + private predicate ssa_definition_points_to( + EssaDefinition def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { ssa_phi_points_to(def, context, value, origin) or exists(ControlFlowNode orig | @@ -398,14 +427,18 @@ cached module PointsToInternal { ssa_node_refinement_points_to(def, context, value, origin) } - pragma [noinline] - private predicate ssa_node_definition_points_to(EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate ssa_node_definition_points_to( + EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { reachableBlock(def.getDefiningNode().getBasicBlock(), context) and ssa_node_definition_points_to_unpruned(def, context, value, origin) } - pragma [nomagic] - private predicate ssa_node_definition_points_to_unpruned(EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[nomagic] + private predicate ssa_node_definition_points_to_unpruned( + EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { InterProceduralPointsTo::parameter_points_to(def, context, value, origin) or assignment_points_to(def, context, value, origin) @@ -424,10 +457,13 @@ cached module PointsToInternal { /* * No points-to for non-local function entry definitions yet. */ - } - pragma [noinline] - private predicate ssa_node_refinement_points_to(EssaNodeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + } + + pragma[noinline] + private predicate ssa_node_refinement_points_to( + EssaNodeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { method_callsite_points_to(def, context, value, origin) or InterModulePointsTo::import_star_points_to(def, context, value, origin) @@ -442,20 +478,26 @@ cached module PointsToInternal { } /** Pass through for `self` for the implicit re-definition of `self` in `self.foo()`. */ - private predicate method_callsite_points_to(MethodCallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + private predicate method_callsite_points_to( + MethodCallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { /* The value of self remains the same, only the attributes may change */ variablePointsTo(def.getInput(), context, value, origin) } /** Attribute deletions have no effect as far as value tracking is concerned. */ - pragma [noinline] - private predicate attribute_delete_points_to(EssaAttributeDeletion def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attribute_delete_points_to( + EssaAttributeDeletion def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { variablePointsTo(def.getInput(), context, value, origin) } /** Attribute assignments have no effect as far as value tracking is concerned, except for `__class__`. */ - pragma [noinline] - private predicate attribute_assignment_points_to(AttributeAssignment def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attribute_assignment_points_to( + AttributeAssignment def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { def.getName() = "__class__" and exists(ObjectInternal cls | pointsTo(def.getValue(), context, cls, _) and @@ -464,30 +506,42 @@ cached module PointsToInternal { ) } - private predicate self_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate self_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { origin = def.getDefiningNode() and value.(SelfInstanceInternal).parameterAndContext(def, context) } /** Holds if ESSA edge refinement, `def`, refers to `(value, cls, origin)`. */ - private predicate ssa_filter_definition_points_to(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + private predicate ssa_filter_definition_points_to( + PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { exists(ControlFlowNode orig | def.getSense() = ssa_filter_definition_bool(def, context, value, orig) and origin = CfgOrigin::fromCfgNode(orig) ) } - private boolean ssa_filter_definition_bool(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { - result = Conditionals::testEvaluates(def.getTest(), def.getInput().getASourceUse(), context, value, origin) + private boolean ssa_filter_definition_bool( + PyEdgeRefinement def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { + result = + Conditionals::testEvaluates(def.getTest(), def.getInput().getASourceUse(), context, value, + origin) } /** Holds if ESSA definition, `unipi`, refers to `(value, origin)`. */ - pragma [noinline] - private predicate uni_edged_pi_points_to(SingleSuccessorGuard unipi, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate uni_edged_pi_points_to( + SingleSuccessorGuard unipi, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { exists(ControlFlowNode test, ControlFlowNode use, ControlFlowNode orig | - /* Because calls such as `len` may create a new variable, we need to go via the source variable + /* + * Because calls such as `len` may create a new variable, we need to go via the source variable * That is perfectly safe as we are only dealing with calls that do not mutate their arguments. */ + unipi.useAndTest(use, test) and unipi.getSense() = Conditionals::testEvaluates(test, use, context, value, orig) and origin = CfgOrigin::fromCfgNode(orig) @@ -495,13 +549,18 @@ cached module PointsToInternal { } /** Points-to for normal assignments `def = ...`. */ - pragma [noinline] - private predicate assignment_points_to(AssignmentDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate assignment_points_to( + AssignmentDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { pointsTo(def.getValue(), context, value, origin) } - pragma [nomagic] - private predicate sequence_index_points_to(ControlFlowNode f, PointsToContext context, SequenceObjectInternal sequence, ObjectInternal value, int index) { + pragma[nomagic] + private predicate sequence_index_points_to( + ControlFlowNode f, PointsToContext context, SequenceObjectInternal sequence, + ObjectInternal value, int index + ) { pointsTo(f, context, sequence, _) and value = sequence.getItem(index) } @@ -525,18 +584,22 @@ cached module PointsToInternal { } /** Points-to for deletion: `del name`. */ - pragma [noinline] - private predicate delete_points_to(DeletionDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { - value = ObjectInternal::undefined() and origin = def.getDefiningNode() and context.appliesToScope(def.getScope()) + pragma[noinline] + private predicate delete_points_to( + DeletionDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { + value = ObjectInternal::undefined() and + origin = def.getDefiningNode() and + context.appliesToScope(def.getScope()) } /** Implicit "definition" of `__name__` at the start of a module. */ - pragma [noinline] - private predicate module_name_points_to(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate module_name_points_to( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { def.getVariable().getName() = "__name__" and - exists(Module m | - m = def.getScope() - | + exists(Module m | m = def.getScope() | value = module_dunder_name(m) and context.isImport() or value.strValue() = "__main__" and context.isMain() and context.appliesToScope(m) @@ -545,18 +608,16 @@ cached module PointsToInternal { } private ObjectInternal module_dunder_name(Module m) { - exists(string name | - result.strValue() = name | - if m.isPackageInit() then - name = m.getPackage().getName() - else - name = m.getName() + exists(string name | result.strValue() = name | + if m.isPackageInit() then name = m.getPackage().getName() else name = m.getName() ) } /** Holds if the phi-function `phi` refers to `(value, origin)` given the context `context`. */ - pragma [nomagic] - private predicate ssa_phi_points_to(PhiFunction phi, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[nomagic] + private predicate ssa_phi_points_to( + PhiFunction phi, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { exists(EssaVariable input | ssa_phi_reachable_from_input(phi, context, input) and variablePointsTo(input, context, value, origin) @@ -565,7 +626,9 @@ cached module PointsToInternal { /* Helper for ssa_phi_points_to */ cached - predicate ssa_phi_reachable_from_input(PhiFunction phi, PointsToContext context, EssaVariable input) { + predicate ssa_phi_reachable_from_input( + PhiFunction phi, PointsToContext context, EssaVariable input + ) { exists(BasicBlock pred | input = phi.getInput(pred) and reachableEdge(pred, phi.getBasicBlock(), context) @@ -573,8 +636,10 @@ cached module PointsToInternal { } /** Points-to for implicit variable declarations at scope-entry. */ - pragma [noinline] - private predicate scope_entry_points_to(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate scope_entry_points_to( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { /* Transfer from another scope */ exists(EssaVariable var, PointsToContext outer, CfgOrigin orig | InterProceduralPointsTo::scope_entry_value_transfer(var, outer, def, context) and @@ -589,74 +654,91 @@ cached module PointsToInternal { builtin_not_in_outer_scope(def, context, value, origin) } - private predicate undefined_variable(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate undefined_variable( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(Scope scope | not def.getVariable().getName() = "__name__" and not def.getVariable().isMetaVariable() and - def.getScope() = scope and context.appliesToScope(scope) | + def.getScope() = scope and + context.appliesToScope(scope) + | def.getSourceVariable() instanceof GlobalVariable and scope instanceof Module or - def.getSourceVariable() instanceof LocalVariable and (context.isImport() or context.isRuntime() or context.isMain()) + def.getSourceVariable() instanceof LocalVariable and + (context.isImport() or context.isRuntime() or context.isMain()) ) and - value = ObjectInternal::undefined() and origin = def.getDefiningNode() + value = ObjectInternal::undefined() and + origin = def.getDefiningNode() } - private predicate builtin_not_in_outer_scope(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate builtin_not_in_outer_scope( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(Module mod, GlobalVariable var | var = def.getSourceVariable() and mod = def.getScope().getEnclosingModule() and context.appliesToScope(def.getScope()) and not exists(EssaVariable v | v.getSourceVariable() = var and v.getScope() = mod) and - value = ObjectInternal::builtin(var.getId()) and origin = def.getDefiningNode() + value = ObjectInternal::builtin(var.getId()) and + origin = def.getDefiningNode() ) } /** Holds if `f` is an expression node `tval if cond else fval` and points to `(value, origin)`. */ - private predicate if_exp_points_to(IfExprNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate if_exp_points_to( + IfExprNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { pointsTo(f.getAnOperand(), context, value, origin) } /* Holds if `import name` will import the module `m`. */ - cached predicate module_imported_as(ModuleObjectInternal m, string name) { + cached + predicate module_imported_as(ModuleObjectInternal m, string name) { /* Normal imports */ m.getName() = name or /* sys.modules['name'] = m */ exists(ControlFlowNode sys_modules_flow, ControlFlowNode n, ControlFlowNode mod | - /* Use previous points-to here to avoid slowing down the recursion too much */ - exists(SubscriptNode sub | - sub.getObject() = sys_modules_flow and - pointsTo(sys_modules_flow, _, ObjectInternal::sysModules(), _) and - sub.getIndex() = n and - n.getNode().(StrConst).getText() = name and - sub.(DefinitionNode).getValue() = mod and - pointsTo(mod, _, m, _) - ) + /* Use previous points-to here to avoid slowing down the recursion too much */ + exists(SubscriptNode sub | + sub.getObject() = sys_modules_flow and + pointsTo(sys_modules_flow, _, ObjectInternal::sysModules(), _) and + sub.getIndex() = n and + n.getNode().(StrConst).getText() = name and + sub.(DefinitionNode).getValue() = mod and + pointsTo(mod, _, m, _) + ) ) } - } private module InterModulePointsTo { - - pragma [noinline] - predicate import_points_to(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate import_points_to( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(string name, ImportExpr i | - i.getAFlowNode() = f and i.getImportedModuleName() = name and + i.getAFlowNode() = f and + i.getImportedModuleName() = name and PointsToInternal::module_imported_as(value, name) and origin = f and context.appliesTo(f) ) } - predicate from_import_points_to(ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + predicate from_import_points_to( + ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { from_self_import_points_to(f, context, value, origin) or from_other_import_points_to(f, context, value, origin) } - pragma [noinline] - predicate from_self_import_points_to(ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate from_self_import_points_to( + ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(EssaVariable var, CfgOrigin orig | var = ssa_variable_for_module_attribute(f, context) and PointsToInternal::variablePointsTo(var, context, value, orig) and @@ -664,8 +746,10 @@ private module InterModulePointsTo { ) } - pragma [noinline] - predicate from_other_import_points_to(ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate from_other_import_points_to( + ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(string name, ModuleObjectInternal mod, CfgOrigin orig | from_import_imports(f, context, mod, name) and (mod.getSourceModule() != f.getEnclosingModule() or mod.isBuiltin()) and @@ -674,48 +758,60 @@ private module InterModulePointsTo { ) or PointsToInternal::pointsTo(f.getModule(_), context, ObjectInternal::unknown(), _) and - value = ObjectInternal::unknown() and origin = f + value = ObjectInternal::unknown() and + origin = f } - private predicate from_import_imports(ImportMemberNode f, PointsToContext context, ModuleObjectInternal mod, string name) { + private predicate from_import_imports( + ImportMemberNode f, PointsToContext context, ModuleObjectInternal mod, string name + ) { PointsToInternal::pointsTo(f.getModule(name), context, mod, _) } - pragma [noinline] + pragma[noinline] private EssaVariable ssa_variable_for_module_attribute(ImportMemberNode f, PointsToContext context) { exists(string name, ModuleObjectInternal mod, Module m | - mod.getSourceModule() = m and m = result.getScope() and + mod.getSourceModule() = m and + m = result.getScope() and PointsToInternal::pointsTo(f.getModule(name), context, mod, _) and result = ssa_variable_for_module_attribute_helper(f, name, m) ) } - pragma [noinline] - private EssaVariable ssa_variable_for_module_attribute_helper(ImportMemberNode f, string name, Module m) { - result.getSourceVariable().getName() = name and result.getAUse() = f - and m = f.getEnclosingModule() + pragma[noinline] + private EssaVariable ssa_variable_for_module_attribute_helper( + ImportMemberNode f, string name, Module m + ) { + result.getSourceVariable().getName() = name and + result.getAUse() = f and + m = f.getEnclosingModule() } /* Helper for implicit_submodule_points_to */ private ModuleObjectInternal getModule(ImplicitSubModuleDefinition def) { - exists(PackageObjectInternal package | - package.getSourceModule() = def.getDefiningNode().getScope() and - result = package.submodule(def.getSourceVariable().getName()) - ) + exists(PackageObjectInternal package | + package.getSourceModule() = def.getDefiningNode().getScope() and + result = package.submodule(def.getSourceVariable().getName()) + ) } - /** Implicit "definition" of the names of submodules at the start of an `__init__.py` file. + /** + * Implicit "definition" of the names of submodules at the start of an `__init__.py` file. * * PointsTo isn't exactly how the interpreter works, but is the best approximation we can manage statically. */ - pragma [noinline] - predicate implicit_submodule_points_to(ImplicitSubModuleDefinition def, ModuleObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate implicit_submodule_points_to( + ImplicitSubModuleDefinition def, ModuleObjectInternal value, ControlFlowNode origin + ) { value = getModule(def) and origin = CfgOrigin::fromObject(value).asCfgNodeOrHere(def.getDefiningNode()) } /** Points-to for `from ... import *`. */ - predicate import_star_points_to(ImportStarRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + predicate import_star_points_to( + ImportStarRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { /* Attribute from imported module */ exists(CfgOrigin orig, ImportStarNode imp, ModuleObjectInternal mod, string name | imp = def.getDefiningNode() and @@ -733,18 +829,22 @@ private module InterModulePointsTo { ) } - /** Holds if `def` is technically a definition of `var`, but the `from ... import *` does not in fact define `var`. */ - cached predicate variable_not_redefined_by_import_star(EssaVariable var, PointsToContext context, ImportStarRefinement def) { + cached + predicate variable_not_redefined_by_import_star( + EssaVariable var, PointsToContext context, ImportStarRefinement def + ) { var = def.getInput() and exists(ModuleObjectInternal mod | - PointsToInternal::pointsTo(def.getDefiningNode().(ImportStarNode).getModule(), context, mod, _) | + PointsToInternal::pointsTo(def.getDefiningNode().(ImportStarNode).getModule(), context, mod, _) + | moduleExportsBoolean(mod, var.getSourceVariable().getName()) = false or var.getSourceVariable().getName().charAt(0) = "_" or exists(Module m, string name | - m = mod.getSourceModule() and name = var.getSourceVariable().getName() | + m = mod.getSourceModule() and name = var.getSourceVariable().getName() + | not m.declaredInAll(_) and name.charAt(0) = "_" ) ) @@ -755,12 +855,10 @@ private module InterModulePointsTo { imp = def.getDefiningNode() and PointsToInternal::importCtxPointsTo(imp.getModule(), mod, _) and var = def.getVariable() - | - if var.isMetaVariable() then ( - ModuleAttributes::attributePointsTo(def.getInput().getDefinition(), name, _, _) - ) else ( - def.getVariable().getName() = name - ) + | + if var.isMetaVariable() + then ModuleAttributes::attributePointsTo(def.getInput().getDefinition(), name, _, _) + else def.getVariable().getName() = name ) or exists(PackageObjectInternal package | @@ -770,19 +868,16 @@ private module InterModulePointsTo { } private boolean pythonModuleExportsBoolean(PythonModuleObjectInternal mod, string name) { - exists(Module src | - src = mod.getSourceModule() - | + exists(Module src | src = mod.getSourceModule() | src.declaredInAll(name) and result = true or declared_all_is_simple(src) and not src.declaredInAll(name) and - ofInterestInExports(mod, name) and result = false + ofInterestInExports(mod, name) and + result = false or - (not src.declaredInAll(name) and not declared_all_is_simple(src)) - and - exists(ObjectInternal val | - ModuleAttributes::pointsToAtExit(src, name, val, _) | + (not src.declaredInAll(name) and not declared_all_is_simple(src)) and + exists(ObjectInternal val | ModuleAttributes::pointsToAtExit(src, name, val, _) | val = ObjectInternal::undefined() and result = false or val != ObjectInternal::undefined() and result = true @@ -793,23 +888,24 @@ private module InterModulePointsTo { /** Holds if __all__ is declared and not mutated */ private predicate declared_all_is_simple(Module m) { exists(AssignStmt a, GlobalVariable all | - a.defines(all) and a.getScope() = m and + a.defines(all) and + a.getScope() = m and all.getId() = "__all__" and - not exists(Attribute attr | - all.getALoad() = attr.getObject() - ) + not exists(Attribute attr | all.getALoad() = attr.getObject()) ) } private boolean packageExportsBoolean(PackageObjectInternal mod, string name) { - exists(Folder folder | - folder = mod.getFolder() | + exists(Folder folder | folder = mod.getFolder() | exportsSubmodule(folder, name) and result = true or - not exportsSubmodule(folder, name) and result = moduleExportsBoolean(mod.getInitModule(), name) + not exportsSubmodule(folder, name) and + result = moduleExportsBoolean(mod.getInitModule(), name) or - mod.hasNoInitModule() and not exportsSubmodule(folder, name) and - ofInterestInExports(mod, name) and result = false + mod.hasNoInitModule() and + not exportsSubmodule(folder, name) and + ofInterestInExports(mod, name) and + result = false ) } @@ -823,8 +919,7 @@ private module InterModulePointsTo { } boolean builtinModuleExportsBoolean(BuiltinModuleObjectInternal mod, string name) { - exists(Builtin bltn | - bltn = mod.getBuiltin() | + exists(Builtin bltn | bltn = mod.getBuiltin() | exists(bltn.getMember(name)) and result = true or ofInterestInExports(mod, name) and not exists(bltn.getMember(name)) and result = false @@ -841,29 +936,34 @@ private module InterModulePointsTo { result = builtinModuleExportsBoolean(mod, name) ) } - } module InterProceduralPointsTo { - - cached predicate call(CallNode call, PointsToContext caller, ObjectInternal value) { + cached + predicate call(CallNode call, PointsToContext caller, ObjectInternal value) { PointsToInternal::pointsTo(call.getFunction(), caller, value, _) } - cached predicate callWithContext(CallNode call, PointsToContext caller, ObjectInternal value, PointsToContext callee) { + cached + predicate callWithContext( + CallNode call, PointsToContext caller, ObjectInternal value, PointsToContext callee + ) { callee.fromCall(call, caller) and PointsToInternal::pointsTo(call.getFunction(), caller, value, _) } - pragma [noinline] - predicate call_points_to(CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate call_points_to( + CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { /* Either not a decorator, or we understand the return value */ (value != ObjectInternal::unknown() or not f.isDecoratorCall()) and call_points_to_from_callee(f, context, value, origin) or f.isFunctionDecoratorCall() and call_points_to_from_callee(f, context, ObjectInternal::unknown(), _) and - value = TDecoratedFunction(f) and origin = f + value = TDecoratedFunction(f) and + origin = f or f.isClassDecoratorCall() and call_points_to_from_callee(f, context, ObjectInternal::unknown(), _) and @@ -876,11 +976,11 @@ module InterProceduralPointsTo { } /** Helper for call_points_to to improve join-order */ - pragma [noinline] - private predicate call_points_to_from_callee(CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { - exists(ObjectInternal func | - call(f, context, func) - | + pragma[noinline] + private predicate call_points_to_from_callee( + CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { + exists(ObjectInternal func | call(f, context, func) | exists(CfgOrigin orig, PointsToContext callee | callee.fromCall(f, context) and func.callResult(callee, value, orig) and @@ -889,7 +989,8 @@ module InterProceduralPointsTo { or context.untrackableCall(f) and func.contextSensitiveCallee() and - value = ObjectInternal::unknown() and origin = f + value = ObjectInternal::unknown() and + origin = f or exists(CfgOrigin orig | func.callResult(value, orig) and @@ -900,8 +1001,10 @@ module InterProceduralPointsTo { } /** Points-to for parameter. `def foo(param): ...`. */ - pragma [noinline] - predicate parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { self_parameter_points_to(def, context, value, origin) or normal_parameter_points_to(def, context, value, origin) @@ -912,21 +1015,29 @@ module InterProceduralPointsTo { } /** Helper for `parameter_points_to` */ - pragma [noinline] - private predicate normal_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate normal_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(PointsToContext caller, ControlFlowNode arg | PointsToInternal::pointsTo(arg, caller, value, origin) and named_argument_transfer(arg, caller, def, context) ) or - not def.isSelf() and not def.isVarargs() and not def.isKwargs() and - context.isRuntime() and value = ObjectInternal::unknown() and origin = def.getDefiningNode() + not def.isSelf() and + not def.isVarargs() and + not def.isKwargs() and + context.isRuntime() and + value = ObjectInternal::unknown() and + origin = def.getDefiningNode() or positional_parameter_points_to(def, context, value, origin) } - pragma [noinline] - private predicate self_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate self_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { def.isSelf() and exists(CallNode call, BoundMethodObjectInternal method, Function func, PointsToContext caller | callWithContext(call, caller, method, context) and @@ -937,7 +1048,9 @@ module InterProceduralPointsTo { ) } - predicate selfMethodCall(SelfCallsiteRefinement def, PointsToContext caller, Function func, PointsToContext callee) { + predicate selfMethodCall( + SelfCallsiteRefinement def, PointsToContext caller, Function func, PointsToContext callee + ) { def.getInput().getSourceVariable().(Variable).isSelf() and exists(PythonFunctionObjectInternal method, CallNode call | method.getScope() = func and @@ -948,14 +1061,16 @@ module InterProceduralPointsTo { } /** Helper for parameter_points_to */ - pragma [noinline] - private predicate default_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate default_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { PointsToInternal::importCtxPointsTo(def.getDefault(), value, origin) and context_for_default_value(def, context) } /** Helper for default_parameter_points_to */ - pragma [noinline] + pragma[noinline] private predicate context_for_default_value(ParameterDefinition def, PointsToContext context) { context.isRuntime() or @@ -970,8 +1085,10 @@ module InterProceduralPointsTo { } /** Helper for parameter_points_to */ - pragma [noinline] - private predicate special_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate special_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { /* Runtime: Just an unknown tuple (or dict for `**` args) */ special_parameter_value(def, value) and context.isRuntime() and @@ -996,11 +1113,15 @@ module InterProceduralPointsTo { origin = def.getDefiningNode() } - /** Holds if `call` in context `caller` calls into the function scope `scope` in context `callee` and + /** + * Holds if `call` in context `caller` calls into the function scope `scope` in context `callee` and * that the number of position arguments (including expansion of `*` argument) exceeds the number of positional arguments by * `length` and that the excess arguments start at `start`. */ - predicate varargs_tuple(CallNode call, PointsToContext caller, Function scope, PointsToContext callee, int start, int length) { + predicate varargs_tuple( + CallNode call, PointsToContext caller, Function scope, PointsToContext callee, int start, + int length + ) { exists(int parameter_offset | callsite_calls_function(call, caller, scope, callee, parameter_offset) and start = scope.getPositionalParameterCount() - parameter_offset and @@ -1013,7 +1134,8 @@ module InterProceduralPointsTo { predicate varargs_empty_tuple(Function func, PointsToContext callee) { exists(CallNode call, PointsToContext caller, int parameter_offset | callsite_calls_function(call, caller, func, callee, parameter_offset) and - func.getPositionalParameterCount() - parameter_offset >= positional_argument_count(call, caller) + func.getPositionalParameterCount() - parameter_offset >= + positional_argument_count(call, caller) ) } @@ -1024,23 +1146,28 @@ module InterProceduralPointsTo { p.isKwargs() and value = TUnknownInstance(ObjectInternal::builtin("dict")) } - /** Holds if the `n`th argument in call `call` with context `caller` points-to `value` from `origin`, including values in tuples + /** + * Holds if the `n`th argument in call `call` with context `caller` points-to `value` from `origin`, including values in tuples * expanded by a `*` argument. For example, for the call `f('a', *(`x`,`y`))` the arguments are `('a', 'x', y')` */ - predicate positional_argument_points_to(CallNode call, int n, PointsToContext caller, ObjectInternal value, ControlFlowNode origin) { + predicate positional_argument_points_to( + CallNode call, int n, PointsToContext caller, ObjectInternal value, ControlFlowNode origin + ) { PointsToInternal::pointsTo(call.getArg(n), caller, value, origin) or exists(SequenceObjectInternal arg, int pos | pos = call.getNode().getPositionalArgumentCount() and PointsToInternal::pointsTo(origin, caller, arg, _) and - value = arg.getItem(n-pos) and + value = arg.getItem(n - pos) and origin = call.getStarArg() ) } - /** Gets the number of positional arguments including values in tuples expanded by a `*` argument.*/ + /** Gets the number of positional arguments including values in tuples expanded by a `*` argument. */ private int positional_argument_count(CallNode call, PointsToContext caller) { - result = call.getNode().getPositionalArgumentCount() and not exists(call.getStarArg()) and caller.appliesTo(call) + result = call.getNode().getPositionalArgumentCount() and + not exists(call.getStarArg()) and + caller.appliesTo(call) or exists(SequenceObjectInternal arg, int pos | pos = call.getNode().getPositionalArgumentCount() and @@ -1050,19 +1177,25 @@ module InterProceduralPointsTo { } /** Holds if the parameter definition `def` points-to `value` from `origin` given the context `context` */ - predicate positional_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + predicate positional_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(CallNode call, int argument, PointsToContext caller, Function func, int offset | positional_argument_points_to(call, argument, caller, value, origin) and callsite_calls_function(call, caller, func, context, offset) and - def.getParameter() = func.getArg(argument+offset) + def.getParameter() = func.getArg(argument + offset) ) } /** Holds if the named `argument` given the context `caller` is transferred to the parameter `param` with conntext `callee` by a call. */ - cached predicate named_argument_transfer(ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, PointsToContext callee) { + cached + predicate named_argument_transfer( + ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, + PointsToContext callee + ) { exists(CallNode call, Function func, int offset | callsite_calls_function(call, caller, func, callee, offset) - | + | exists(string name | argument = call.getArgByName(name) and param.getParameter() = func.getArgByName(name) @@ -1070,10 +1203,15 @@ module InterProceduralPointsTo { ) } - /** Holds if the `call` with context `caller` calls the function `scope` in context `callee` + /** + * Holds if the `call` with context `caller` calls the function `scope` in context `callee` * and the offset from argument to parameter is `parameter_offset` */ - cached predicate callsite_calls_function(CallNode call, PointsToContext caller, Function scope, PointsToContext callee, int parameter_offset) { + cached + predicate callsite_calls_function( + CallNode call, PointsToContext caller, Function scope, PointsToContext callee, + int parameter_offset + ) { exists(ObjectInternal func | callWithContext(call, caller, func, callee) and func.calleeAndOffset(scope, parameter_offset) @@ -1081,34 +1219,56 @@ module InterProceduralPointsTo { } /** Model the transfer of values at scope-entry points. Transfer from `(pred_var, pred_context)` to `(succ_def, succ_context)`. */ - cached predicate scope_entry_value_transfer(EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, PointsToContext succ_context) { + cached + predicate scope_entry_value_transfer( + EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, + PointsToContext succ_context + ) { scope_entry_value_transfer_from_earlier(pred_var, pred_context, succ_def, succ_context) or callsite_entry_value_transfer(pred_var, pred_context, succ_def, succ_context) or - pred_context.isImport() and pred_context = succ_context and + pred_context.isImport() and + pred_context = succ_context and class_entry_value_transfer(pred_var, succ_def) } - /** Helper for `scope_entry_value_transfer`. Transfer of values from a temporally earlier scope to later scope. - * Earlier and later scopes are, for example, a module and functions in that module, or an __init__ method and another method. */ - pragma [noinline] - private predicate scope_entry_value_transfer_from_earlier(EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, PointsToContext succ_context) { + /** + * Helper for `scope_entry_value_transfer`. Transfer of values from a temporally earlier scope to later scope. + * Earlier and later scopes are, for example, a module and functions in that module, or an __init__ method and another method. + */ + pragma[noinline] + private predicate scope_entry_value_transfer_from_earlier( + EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, + PointsToContext succ_context + ) { exists(Scope pred_scope, Scope succ_scope | BaseFlow::scope_entry_value_transfer_from_earlier(pred_var, pred_scope, succ_def, succ_scope) and succ_context.appliesToScope(succ_scope) - | + | succ_context.isRuntime() and succ_context = pred_context or - pred_context.isImport() and pred_scope instanceof ImportTimeScope and - (succ_context.fromRuntime() or - /* A call made at import time, but from another module. Assume this module has been fully imported. */ - succ_context.isCall() and exists(CallNode call | succ_context.fromCall(call, _) and call.getEnclosingModule() != pred_scope)) + pred_context.isImport() and + pred_scope instanceof ImportTimeScope and + ( + succ_context.fromRuntime() + or + /* A call made at import time, but from another module. Assume this module has been fully imported. */ + succ_context.isCall() and + exists(CallNode call | + succ_context.fromCall(call, _) and call.getEnclosingModule() != pred_scope + ) + ) or - /* If predecessor scope is main, then we assume that any global defined exactly once + /* + * If predecessor scope is main, then we assume that any global defined exactly once * is available to all functions. Although not strictly true, this gives less surprising - * results in practice. */ - pred_context.isMain() and pred_scope instanceof Module and succ_context.fromRuntime() and + * results in practice. + */ + + pred_context.isMain() and + pred_scope instanceof Module and + succ_context.fromRuntime() and exists(Variable v | v = pred_var.getSourceVariable() and not strictcount(v.getAStore()) > 1 @@ -1116,16 +1276,23 @@ module InterProceduralPointsTo { ) or exists(NonEscapingGlobalVariable var | - var = pred_var.getSourceVariable() and var = succ_def.getSourceVariable() and - pred_var.getAUse() = succ_context.getRootCall() and pred_context.isImport() and + var = pred_var.getSourceVariable() and + var = succ_def.getSourceVariable() and + pred_var.getAUse() = succ_context.getRootCall() and + pred_context.isImport() and succ_context.appliesToScope(succ_def.getScope()) ) } - /** Helper for `scope_entry_value_transfer`. - * Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters. */ - pragma [noinline] - private predicate callsite_entry_value_transfer(EssaVariable caller_var, PointsToContext caller, ScopeEntryDefinition entry_def, PointsToContext callee) { + /** + * Helper for `scope_entry_value_transfer`. + * Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters. + */ + pragma[noinline] + private predicate callsite_entry_value_transfer( + EssaVariable caller_var, PointsToContext caller, ScopeEntryDefinition entry_def, + PointsToContext callee + ) { exists(ControlFlowNode use, SsaSourceVariable var | var_and_use(caller_var, use, var) and entry_def.getSourceVariable() = var and @@ -1148,15 +1315,18 @@ module InterProceduralPointsTo { ) } - /** Points-to for a variable (possibly) redefined by a call: + /** + * Points-to for a variable (possibly) redefined by a call: * `var = ...; foo(); use(var)` * Where var may be redefined in call to `foo` if `var` escapes (is global or non-local). */ - pragma [noinline] - predicate callsite_points_to(CallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { - exists(SsaSourceVariable srcvar | - srcvar = def.getSourceVariable() | - if srcvar instanceof EscapingAssignmentGlobalVariable then ( + pragma[noinline] + predicate callsite_points_to( + CallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { + exists(SsaSourceVariable srcvar | srcvar = def.getSourceVariable() | + if srcvar instanceof EscapingAssignmentGlobalVariable + then /* If global variable can be reassigned, we need to track it through calls */ exists(EssaVariable var, Function func, PointsToContext callee | callsite_calls_function(def.getCall(), context, func, callee, _) and @@ -1169,10 +1339,9 @@ module InterProceduralPointsTo { exists(callable.getBuiltin()) and PointsToInternal::variablePointsTo(def.getInput(), context, value, origin) ) - ) else ( + else /* Otherwise we can assume its value (but not those of its attributes or members) has not changed. */ PointsToInternal::variablePointsTo(def.getInput(), context, value, origin) - ) ) } @@ -1184,29 +1353,36 @@ module InterProceduralPointsTo { BaseFlow::reaches_exit(evar) } - /** INTERNAL -- Use `FunctionObject.neverReturns()` instead. + /** + * INTERNAL -- Use `FunctionObject.neverReturns()` instead. * Whether function `func` never returns. Slightly conservative approximation, this predicate may be false - * for a function that can never return. */ - cached predicate neverReturns(Function f) { - /* A Python function never returns if it has no normal exits that are not dominated by a + * for a function that can never return. + */ + cached + predicate neverReturns(Function f) { + /* + * A Python function never returns if it has no normal exits that are not dominated by a * call to a function which itself never returns. */ - forall(BasicBlock exit | - exit = f.getANormalExit().getBasicBlock() | - exists(FunctionObject callee, BasicBlock call | + + forall(BasicBlock exit | exit = f.getANormalExit().getBasicBlock() | + exists(FunctionObject callee, BasicBlock call | callee.getACall().getBasicBlock() = call and callee.neverReturns() and call.dominates(exit) ) ) } - } /** Gets the `value, origin` that `f` would refer to if it has not been assigned some other value */ -pragma [noinline] -private predicate potential_builtin_points_to(NameNode f, ObjectInternal value, ControlFlowNode origin) { - f.isGlobal() and f.isLoad() and origin = f and +pragma[noinline] +private predicate potential_builtin_points_to( + NameNode f, ObjectInternal value, ControlFlowNode origin +) { + f.isGlobal() and + f.isLoad() and + origin = f and ( value = ObjectInternal::builtin(f.getId()) or @@ -1214,20 +1390,23 @@ private predicate potential_builtin_points_to(NameNode f, ObjectInternal value, ) } - module Expressions { - - pragma [noinline] - private predicate attributeObjectPointsto(AttrNode attr, PointsToContext context, string name, ControlFlowNode obj, ObjectInternal objvalue) { - attr.isLoad() and attr.getObject(name) = obj and + pragma[noinline] + private predicate attributeObjectPointsto( + AttrNode attr, PointsToContext context, string name, ControlFlowNode obj, + ObjectInternal objvalue + ) { + attr.isLoad() and + attr.getObject(name) = obj and PointsToInternal::pointsTo(obj, context, objvalue, _) } - pragma [noinline] - predicate attributePointsTo(AttrNode attr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode obj, ObjectInternal objvalue) { - exists(string name | - attributeObjectPointsto(attr, context, name, obj, objvalue) - | + pragma[noinline] + predicate attributePointsTo( + AttrNode attr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode obj, ObjectInternal objvalue + ) { + exists(string name | attributeObjectPointsto(attr, context, name, obj, objvalue) | exists(CfgOrigin orig | objvalue.attribute(name, value, orig) and origin = orig.asCfgNodeOrHere(attr) @@ -1239,11 +1418,12 @@ module Expressions { ) } - pragma [noinline] - predicate subscriptPointsTo(SubscriptNode subscr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode obj, ObjectInternal objvalue) { - exists(ControlFlowNode index | - subscriptObjectAndIndex(subscr, context, obj, objvalue, index) - | + pragma[noinline] + predicate subscriptPointsTo( + SubscriptNode subscr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode obj, ObjectInternal objvalue + ) { + exists(ControlFlowNode index | subscriptObjectAndIndex(subscr, context, obj, objvalue, index) | objvalue.subscriptUnknown() and value = ObjectInternal::unknown() or @@ -1255,25 +1435,35 @@ module Expressions { origin = subscr } - predicate subscriptPartsPointsTo(SubscriptNode subscr, PointsToContext context, ObjectInternal objvalue, ObjectInternal indexvalue) { + predicate subscriptPartsPointsTo( + SubscriptNode subscr, PointsToContext context, ObjectInternal objvalue, + ObjectInternal indexvalue + ) { exists(ControlFlowNode index | subscriptObjectAndIndex(subscr, context, _, objvalue, index) and PointsToInternal::pointsTo(index, context, indexvalue, _) ) } - pragma [noinline] - private predicate subscriptObjectAndIndex(SubscriptNode subscr, PointsToContext context, ControlFlowNode obj, ObjectInternal objvalue, ControlFlowNode index) { + pragma[noinline] + private predicate subscriptObjectAndIndex( + SubscriptNode subscr, PointsToContext context, ControlFlowNode obj, ObjectInternal objvalue, + ControlFlowNode index + ) { subscr.isLoad() and obj = subscr.getObject() and PointsToInternal::pointsTo(obj, context, objvalue, _) and index = subscr.getIndex() } - /** Tracking too many binary expressions is likely to kill performance, so just say anything other than addition or bitwise or is 'unknown'. + /** + * Tracking too many binary expressions is likely to kill performance, so just say anything other than addition or bitwise or is 'unknown'. */ - pragma [noinline] - predicate binaryPointsTo(BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate binaryPointsTo( + BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { origin = b and operand = genericBinaryOperand(b) and PointsToInternal::pointsTo(operand, context, opvalue, _) and @@ -1285,34 +1475,40 @@ module Expressions { b.operands(result, op, _) or b.operands(_, op, result) - | + | not op instanceof BitOr and not op instanceof Add ) } - pragma [noinline] - predicate addPointsTo(BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate addPointsTo( + BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { origin = b and exists(Operator op | b.operands(operand, op, _) or b.operands(_, op, operand) - | + | op instanceof Add and PointsToInternal::pointsTo(operand, context, opvalue, _) and value = TUnknownInstance(opvalue.getClass()) ) } - pragma [noinline] - predicate bitOrPointsTo(BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate bitOrPointsTo( + BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { origin = b and exists(Operator op, ControlFlowNode other | b.operands(operand, op, other) or b.operands(other, op, operand) - | + | op instanceof BitOr and exists(ObjectInternal obj, int i1, int i2 | pointsToInt(operand, context, opvalue, i1) and @@ -1327,13 +1523,16 @@ module Expressions { value = obj.intValue() } - pragma [noinline] - predicate unaryPointsTo(UnaryExprNode u, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate unaryPointsTo( + UnaryExprNode u, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { exists(Unaryop op | op = u.getNode().getOp() and operand = u.getOperand() and PointsToInternal::pointsTo(operand, context, opvalue, _) - | + | op instanceof Not and value = ObjectInternal::bool(opvalue.booleanValue().booleanNot()) or op instanceof USub and value = ObjectInternal::fromInt(-opvalue.intValue()) @@ -1343,12 +1542,16 @@ module Expressions { origin = u } - pragma [noinline] - predicate builtinCallPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { + pragma[noinline] + predicate builtinCallPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { PointsToInternal::pointsTo(arg, context, argvalue, _) and arg = call.getArg(0) and exists(BuiltinFunctionObjectInternal callable | - PointsToInternal::pointsTo(call.getFunction(), context, callable, _) | + PointsToInternal::pointsTo(call.getFunction(), context, callable, _) + | callable != ObjectInternal::builtin("len") and callable != ObjectInternal::builtin("callable") and callable != ObjectInternal::builtin("isinstance") and @@ -1360,31 +1563,36 @@ module Expressions { origin = call } - pragma [noinline] - predicate typeCallPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { + pragma[noinline] + predicate typeCallPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { type_call1(call, arg, context, argvalue) and value = argvalue.getClass() and origin = CfgOrigin::fromObject(value).asCfgNodeOrHere(call) } - pragma [noinline] - private predicate lenCallPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { + pragma[noinline] + private predicate lenCallPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { len_call(call, arg, context, argvalue) and origin = call and - exists(int len | - len = argvalue.length() - | + exists(int len | len = argvalue.length() | value = TInt(len) and len >= 0 or len < 0 and value = TUnknownInstance(ObjectInternal::builtin("int")) ) } - pragma [noinline] - private predicate getattrPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { - exists(string name | - getattr_call(call, arg, context, argvalue, name) - | + pragma[noinline] + private predicate getattrPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { + exists(string name | getattr_call(call, arg, context, argvalue, name) | argvalue.attributesUnknown() and value = ObjectInternal::unknown() and origin = call or exists(CfgOrigin valOrigin | @@ -1393,8 +1601,10 @@ module Expressions { ) } - pragma [noinline] - predicate getattr_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name) { + pragma[noinline] + predicate getattr_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name + ) { exists(ControlFlowNode arg1 | call_and_args_for_getattr(call, context, use, arg1) and PointsToInternal::pointsTo(use, context, val, _) and @@ -1403,15 +1613,20 @@ module Expressions { } pragma[noinline] - private predicate call_and_args_for_getattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1) { + private predicate call_and_args_for_getattr( + ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1 + ) { exists(ControlFlowNode func | call2(call, func, arg0, arg1) and PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("getattr"), _) ) } - pragma [noinline] - predicate setattr_call(CallNode call, PointsToContext context, ControlFlowNode obj, string name, ObjectInternal val, ControlFlowNode origin) { + pragma[noinline] + predicate setattr_call( + CallNode call, PointsToContext context, ControlFlowNode obj, string name, ObjectInternal val, + ControlFlowNode origin + ) { exists(ControlFlowNode arg1, ControlFlowNode arg2 | call_and_args_for_setattr(call, context, obj, arg1, arg2) and PointsToInternal::pointsTo(arg2, context, val, origin) and @@ -1420,29 +1635,37 @@ module Expressions { } pragma[noinline] - private predicate call_and_args_for_setattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1, ControlFlowNode arg2) { + private predicate call_and_args_for_setattr( + ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1, + ControlFlowNode arg2 + ) { exists(ControlFlowNode func | call3(call, func, arg0, arg1, arg2) and PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("setattr"), _) ) } - pragma [noinline] - private boolean containsComparisonEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + private boolean containsComparisonEvaluatesTo( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue + ) { exists(Cmpop op | comp.operands(operand, op, _) or comp.operands(_, op, operand) - | + | (op instanceof In or op instanceof NotIn) and PointsToInternal::pointsTo(operand, context, opvalue, _) - ) and result = maybe() + ) and + result = maybe() } - pragma [noinline] - private boolean equalityEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + private boolean equalityEvaluatesTo( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue + ) { exists(ObjectInternal other, boolean sense | equalityTest(comp, context, operand, opvalue, other, sense) - | + | other = opvalue and result = sense or other != opvalue and result = sense.booleanNot() @@ -1453,16 +1676,21 @@ module Expressions { ) } - pragma [noinline] - private boolean comparesToUnknown(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + private boolean comparesToUnknown( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue + ) { (comp.operands(operand, _, _) or comp.operands(_, _, operand)) and PointsToInternal::pointsTo(operand, context, opvalue, _) and opvalue = ObjectInternal::unknown() and result = maybe() } - pragma [noinline] - private predicate equalityTest(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, ObjectInternal other, boolean sense) { + pragma[noinline] + private predicate equalityTest( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, + ObjectInternal other, boolean sense + ) { exists(ControlFlowNode r | equality_test(comp, operand, sense, r) and PointsToInternal::pointsTo(operand, context, opvalue, _) and @@ -1470,11 +1698,13 @@ module Expressions { ) } - pragma [noinline] - private boolean inequalityEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode use, ObjectInternal val) { + pragma[noinline] + private boolean inequalityEvaluatesTo( + CompareNode comp, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { exists(boolean strict, boolean sense, ObjectInternal other | inequalityTest(comp, context, use, val, other, strict, sense) - | + | compare(val, other) = -1 and result = sense or compare(val, other) = 0 and result = strict.booleanNot() @@ -1509,11 +1739,9 @@ module Expressions { val.strValue() = other.strValue() and result = 0 } - pragma [nomagic] + pragma[nomagic] private int compare_sequence(SequenceObjectInternal val, SequenceObjectInternal other, int n) { - exists(int vlen, int olen | - sequence_lengths_in_comparison(val, other, vlen, olen) - | + exists(int vlen, int olen | sequence_lengths_in_comparison(val, other, vlen, olen) | n = vlen and olen > n and result = -1 or n = olen and vlen > n and result = 1 @@ -1523,35 +1751,43 @@ module Expressions { or result != 0 and result = compare_item(val, other, n) or - compare_item(val, other, n) = 0 and result = compare_sequence(val, other, n+1) + compare_item(val, other, n) = 0 and result = compare_sequence(val, other, n + 1) } - private predicate sequence_lengths_in_comparison(SequenceObjectInternal val, SequenceObjectInternal other, int vlen, int olen) { + private predicate sequence_lengths_in_comparison( + SequenceObjectInternal val, SequenceObjectInternal other, int vlen, int olen + ) { inequalityTest(_, _, _, val, other, _, _) and - vlen = val.length() and olen = other.length() + vlen = val.length() and + olen = other.length() } - pragma [noinline] + pragma[noinline] private int compare_item(SequenceObjectInternal val, SequenceObjectInternal other, int n) { inequalityTest(_, _, _, val, other, _, _) and result = compare_unbound(val.getItem(n), other.getItem(n)) } - pragma [noinline] - private predicate inequalityTest(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, ObjectInternal other, boolean strict, boolean sense) { + pragma[noinline] + private predicate inequalityTest( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, + ObjectInternal other, boolean strict, boolean sense + ) { exists(ControlFlowNode r | inequality(comp, operand, r, strict) and sense = true or inequality(comp, r, operand, strict) and sense = false - | + | PointsToInternal::pointsTo(operand, context, opvalue, _) and PointsToInternal::pointsTo(r, context, other, _) ) } /** Helper for comparisons. */ - pragma [noinline] - private predicate inequality(CompareNode cmp, ControlFlowNode lesser, ControlFlowNode greater, boolean strict) { + pragma[noinline] + private predicate inequality( + CompareNode cmp, ControlFlowNode lesser, ControlFlowNode greater, boolean strict + ) { exists(Cmpop op | cmp.operands(lesser, op, greater) and op.getSymbol() = "<" and strict = true or @@ -1563,7 +1799,10 @@ module Expressions { ) } - predicate pointsTo(ControlFlowNode expr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode subexpr, ObjectInternal subvalue) { + predicate pointsTo( + ControlFlowNode expr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode subexpr, ObjectInternal subvalue + ) { attributePointsTo(expr, context, value, origin, subexpr, subvalue) or subscriptPointsTo(expr, context, value, origin, subexpr, subvalue) @@ -1587,8 +1826,10 @@ module Expressions { value = ObjectInternal::bool(evaluatesTo(expr, context, subexpr, subvalue)) and origin = expr } - pragma [noinline] - boolean evaluatesTo(ControlFlowNode expr, PointsToContext context, ControlFlowNode subexpr, ObjectInternal subvalue) { + pragma[noinline] + boolean evaluatesTo( + ControlFlowNode expr, PointsToContext context, ControlFlowNode subexpr, ObjectInternal subvalue + ) { result = equalityEvaluatesTo(expr, context, subexpr, subvalue) or result = inequalityEvaluatesTo(expr, context, subexpr, subvalue) @@ -1606,10 +1847,11 @@ module Expressions { result = hasattrEvaluatesTo(expr, context, subexpr, subvalue) } - pragma [nomagic] - private boolean isinstanceEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { - exists(ObjectInternal cls | - isinstance_call(call, use, context, val, cls) | + pragma[nomagic] + private boolean isinstanceEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { + exists(ObjectInternal cls | isinstance_call(call, use, context, val, cls) | result = Types::improperSubclass(val.getClass(), cls) or val = ObjectInternal::unknown() and result = maybe() @@ -1620,8 +1862,10 @@ module Expressions { ) } - private - predicate isinstance_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls) { + private predicate isinstance_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, + ObjectInternal cls + ) { exists(ControlFlowNode func, ControlFlowNode arg1 | call2(call, func, use, arg1) and points_to_isinstance(func, context) and @@ -1630,8 +1874,10 @@ module Expressions { ) } - private - predicate issubclass_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls) { + private predicate issubclass_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, + ObjectInternal cls + ) { exists(ControlFlowNode func, ControlFlowNode arg1 | call2(call, func, use, arg1) and points_to_issubclass(func, context) and @@ -1650,26 +1896,34 @@ module Expressions { PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("issubclass"), _) } - private predicate callable_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) { + private predicate callable_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val + ) { PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("callable"), _) and use = call.getArg(0) and PointsToInternal::pointsTo(use, context, val, _) } - private predicate len_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) { + private predicate len_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val + ) { PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("len"), _) and use = call.getArg(0) and PointsToInternal::pointsTo(use, context, val, _) } - private predicate type_call1(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) { + private predicate type_call1( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val + ) { PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("type"), _) and use = call.getArg(0) and not exists(call.getArg(1)) and PointsToInternal::pointsTo(use, context, val, _) } - private predicate hasattr_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name) { + private predicate hasattr_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name + ) { exists(ControlFlowNode arg1 | call_to_hasattr(call, context, use, arg1) and PointsToInternal::pointsTo(use, context, val, _) and @@ -1678,17 +1932,20 @@ module Expressions { } pragma[noinline] - private predicate call_to_hasattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1) { + private predicate call_to_hasattr( + ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1 + ) { exists(ControlFlowNode func | call2(call, func, arg0, arg1) and PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("hasattr"), _) ) } - pragma [nomagic] - private boolean issubclassEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { - exists(ObjectInternal cls | - issubclass_call(call, use, context, val, cls) | + pragma[nomagic] + private boolean issubclassEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { + exists(ObjectInternal cls | issubclass_call(call, use, context, val, cls) | result = Types::improperSubclass(val, cls) or val = ObjectInternal::unknownClass() and result = maybe() @@ -1701,8 +1958,10 @@ module Expressions { ) } - pragma [noinline] - private boolean callableEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { + pragma[noinline] + private boolean callableEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { callable_call(call, use, context, val) and ( val = ObjectInternal::unknown() and result = maybe() @@ -1713,11 +1972,11 @@ module Expressions { ) } - pragma [noinline] - private boolean hasattrEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { - exists(string name | - hasattr_call(call, use, context, val, name) - | + pragma[noinline] + private boolean hasattrEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { + exists(string name | hasattr_call(call, use, context, val, name) | val = ObjectInternal::unknown() and result = maybe() or val = ObjectInternal::unknownClass() and result = maybe() @@ -1736,7 +1995,7 @@ module Expressions { isinstance_call(_, _, _, val, sup_or_tuple) and sub = val.getClass() ) - | + | sup = sup_or_tuple or sup = sup_or_tuple.(TupleObjectInternal).getItem(_) @@ -1745,28 +2004,32 @@ module Expressions { predicate requireHasAttr(ClassObjectInternal cls, string name) { cls != ObjectInternal::unknownClass() and - exists(ObjectInternal val | - val.getClass() = cls | + exists(ObjectInternal val | val.getClass() = cls | name = "__call__" and callable_call(_, _, _, val) or hasattr_call(_, _, _, val, name) ) } - } - module Conditionals { - - boolean testEvaluates(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + boolean testEvaluates( + ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal value, + ControlFlowNode origin + ) { pinode_test(expr, use) and result = evaluates(expr, use, context, value, origin).booleanValue() } - pragma [noinline] - ObjectInternal evaluates(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal val, ControlFlowNode origin) { + pragma[noinline] + ObjectInternal evaluates( + ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal val, + ControlFlowNode origin + ) { PointsToInternal::pointsTo(use, context, val, origin) and - pinode_test(_, use) and expr = use and result = val + pinode_test(_, use) and + expr = use and + result = val or exists(ControlFlowNode part, ObjectInternal partval | pinode_test_part(expr, part) and @@ -1793,18 +2056,17 @@ module Conditionals { inner.getAChild*() = use ) } - } -cached module Types { - - cached int base_count(ClassObjectInternal cls) { +cached +module Types { + cached + int base_count(ClassObjectInternal cls) { cls = ObjectInternal::builtin("object") and result = 0 or exists(cls.getBuiltin()) and cls != ObjectInternal::builtin("object") and result = 1 or - exists(Class pycls | - pycls = cls.(PythonClassObjectInternal).getScope() | + exists(Class pycls | pycls = cls.(PythonClassObjectInternal).getScope() | result = strictcount(pycls.getABase()) or isNewStyle(cls) and not exists(pycls.getABase()) and result = 1 @@ -1813,33 +2075,35 @@ cached module Types { ) } - cached ObjectInternal getBase(ClassObjectInternal cls, int n) { + cached + ObjectInternal getBase(ClassObjectInternal cls, int n) { result.getBuiltin() = cls.getBuiltin().getBaseClass() and n = 0 or - exists(Class pycls | - pycls = cls.(PythonClassObjectInternal).getScope() - | + exists(Class pycls | pycls = cls.(PythonClassObjectInternal).getScope() | exists(ObjectInternal base | PointsToInternal::pointsTo(pycls.getBase(n).getAFlowNode(), _, base, _) - | + | result = base and base != ObjectInternal::unknown() or base = ObjectInternal::unknown() and result = ObjectInternal::unknownClass() ) or - not exists(pycls.getABase()) and n = 0 and - isNewStyle(cls) and result = ObjectInternal::builtin("object") + not exists(pycls.getABase()) and + n = 0 and + isNewStyle(cls) and + result = ObjectInternal::builtin("object") ) or - cls = ObjectInternal::unknownClass() and n = 0 and + cls = ObjectInternal::unknownClass() and + n = 0 and result = ObjectInternal::builtin("object") } - cached predicate isOldStyle(ClassObjectInternal cls) { - newStylePython2(cls, 0) = false - } + cached + predicate isOldStyle(ClassObjectInternal cls) { newStylePython2(cls, 0) = false } - cached predicate isNewStyle(ClassObjectInternal cls) { + cached + predicate isNewStyle(ClassObjectInternal cls) { major_version() = 3 or cls.isBuiltin() @@ -1853,23 +2117,26 @@ cached module Types { hasDeclaredMetaclass(cls) = false and exists(Class pycls | pycls = cls.getClassDeclaration().getClass() and - n = count(pycls.getABase()) and result = false + n = count(pycls.getABase()) and + result = false ) or - exists(ClassObjectInternal base | - base = getBase(cls, n) | + exists(ClassObjectInternal base | base = getBase(cls, n) | hasDeclaredMetaclass(cls) = false and - isOldStyle(base) and result = newStylePython2(cls, n+1) + isOldStyle(base) and + result = newStylePython2(cls, n + 1) or isNewStyle(base) and result = true ) or getMro(declaredMetaClass(cls)).contains(ObjectInternal::type()) and - n = 0 and result = true + n = 0 and + result = true ) } - cached ClassList getMro(ClassObjectInternal cls) { + cached + ClassList getMro(ClassObjectInternal cls) { isNewStyle(cls) and result = Mro::newStyleMro(cls) or @@ -1877,8 +2144,12 @@ cached module Types { result = Mro::oldStyleMro(cls) } - cached predicate declaredAttribute(ClassObjectInternal cls, string name, ObjectInternal value, CfgOrigin origin) { - value = ObjectInternal::fromBuiltin(cls.getBuiltin().getMember(name)) and origin = CfgOrigin::unknown() + cached + predicate declaredAttribute( + ClassObjectInternal cls, string name, ObjectInternal value, CfgOrigin origin + ) { + value = ObjectInternal::fromBuiltin(cls.getBuiltin().getMember(name)) and + origin = CfgOrigin::unknown() or value != ObjectInternal::undefined() and exists(EssaVariable var | @@ -1888,7 +2159,8 @@ cached module Types { ) } - cached ClassObjectInternal getMetaClass(PythonClassObjectInternal cls) { + cached + ClassObjectInternal getMetaClass(PythonClassObjectInternal cls) { result = declaredMetaClass(cls) or hasDeclaredMetaclass(cls) = false and result = getInheritedMetaclass(cls) @@ -1896,7 +2168,8 @@ cached module Types { private ClassObjectInternal declaredMetaClass(PythonClassObjectInternal cls) { exists(ObjectInternal obj | - PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) | + PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) + | result = obj or obj = ObjectInternal::unknown() and result = ObjectInternal::unknownClass() @@ -1920,7 +2193,7 @@ cached module Types { exists(ControlFlowNode callee, ObjectInternal func | callee = decorator_call_callee(cls) and PointsToInternal::pointsTo(callee, _, func, _) - | + | func = six_add_metaclass_function() and result = true or func != six_add_metaclass_function() and result = false @@ -1937,7 +2210,8 @@ cached module Types { private boolean has_metaclass_var_metaclass(PythonClassObjectInternal cls) { exists(ObjectInternal obj | - PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) | + PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) + | obj = ObjectInternal::undefined() and result = false or obj != ObjectInternal::undefined() and result = true @@ -1945,29 +2219,37 @@ cached module Types { or exists(Class pycls | pycls = cls.getScope() and - not exists(metaclass_var(pycls)) and result = false + not exists(metaclass_var(pycls)) and + result = false ) } private EssaVariable metaclass_var(Class cls) { result.getASourceUse() = cls.getMetaClass().getAFlowNode() or - major_version() = 2 and not exists(cls.getMetaClass()) and + major_version() = 2 and + not exists(cls.getMetaClass()) and result.getName() = "__metaclass__" and cls.(ImportTimeScope).entryEdge(result.getAUse(), _) } - cached predicate six_add_metaclass(CallNode decorator_call, PointsToContext context, ClassObjectInternal decorated, ControlFlowNode metaclass) { + cached + predicate six_add_metaclass( + CallNode decorator_call, PointsToContext context, ClassObjectInternal decorated, + ControlFlowNode metaclass + ) { exists(CallNode decorator | PointsToInternal::pointsTo(decorator_call.getArg(0), context, decorated, _) and decorator = decorator_call.getFunction() and - decorator.getArg(0) = metaclass | + decorator.getArg(0) = metaclass + | PointsToInternal::pointsTo(decorator.getFunction(), context, six_add_metaclass_function(), _) or exists(ModuleObjectInternal six | - six.getName() = "six" and - PointsToInternal::pointsTo(decorator.getFunction().(AttrNode).getObject("add_metaclass"), context, six, _) - ) + six.getName() = "six" and + PointsToInternal::pointsTo(decorator.getFunction().(AttrNode).getObject("add_metaclass"), + context, six, _) + ) ) } @@ -1978,7 +2260,7 @@ cached module Types { ) } - pragma [nomagic] + pragma[nomagic] private ClassObjectInternal getInheritedMetaclass(ClassObjectInternal cls) { result = getInheritedMetaclass(cls, 0) or @@ -1988,8 +2270,7 @@ cached module Types { /* Helper for getInheritedMetaclass */ private predicate hasUnknownBase(ClassObjectInternal cls) { - exists(ObjectInternal base | - base = getBase(cls, _) | + exists(ObjectInternal base | base = getBase(cls, _) | base.isClass() = false or base = ObjectInternal::unknownClass() @@ -1999,21 +2280,23 @@ cached module Types { private ClassObjectInternal getInheritedMetaclass(ClassObjectInternal cls, int n) { exists(Class c | c = cls.(PythonClassObjectInternal).getScope() and - n = count(c.getABase()) and n != 1 - | + n = count(c.getABase()) and + n != 1 + | result = ObjectInternal::type() and major_version() = 3 or result = ObjectInternal::classType() and major_version() = 2 ) or - base_count(cls) = 1 and n = 0 and + base_count(cls) = 1 and + n = 0 and result = getBase(cls, 0).getClass() or exists(ClassObjectInternal meta1, ClassObjectInternal meta2 | base_count(cls) > 1 and meta1 = getBase(cls, n).getClass() and - meta2 = getInheritedMetaclass(cls, n+1) - | + meta2 = getInheritedMetaclass(cls, n + 1) + | /* Choose sub-class */ improperSuperType(meta1) = meta2 and result = meta1 or @@ -2035,7 +2318,8 @@ cached module Types { } /* Holds if type inference failed to compute the full class hierarchy for this class for the reason given. */ - cached predicate failedInference(ClassObjectInternal cls, string reason) { + cached + predicate failedInference(ClassObjectInternal cls, string reason) { exists(int priority | failedInference(cls, reason, priority) and priority = max(int p | failedInference(cls, _, p)) @@ -2044,41 +2328,60 @@ cached module Types { /* Holds if type inference failed to compute the full class hierarchy for this class for the reason given. */ private predicate failedInference(ClassObjectInternal cls, string reason, int priority) { - strictcount(cls.(PythonClassObjectInternal).getScope().getADecorator()) > 1 and reason = "Multiple decorators" and priority = 0 + strictcount(cls.(PythonClassObjectInternal).getScope().getADecorator()) > 1 and + reason = "Multiple decorators" and + priority = 0 or - exists(cls.(PythonClassObjectInternal).getScope().getADecorator()) and not six_add_metaclass(_, _, cls, _) and reason = "Decorator not understood" and priority = 1 + exists(cls.(PythonClassObjectInternal).getScope().getADecorator()) and + not six_add_metaclass(_, _, cls, _) and + reason = "Decorator not understood" and + priority = 1 or reason = "Missing base " + missingBase(cls) and priority = 6 or - not exists(ObjectInternal meta | meta = cls.getClass() and not meta = ObjectInternal::unknownClass()) and reason = "Failed to infer metaclass" and priority = 4 + not exists(ObjectInternal meta | + meta = cls.getClass() and not meta = ObjectInternal::unknownClass() + ) and + reason = "Failed to infer metaclass" and + priority = 4 or exists(int i, ObjectInternal base1, ObjectInternal base2 | base1 = getBase(cls, i) and base2 = getBase(cls, i) and base1 != base2 and reason = "Multiple bases at position " + i - ) and priority = 6 + ) and + priority = 6 or duplicateBase(cls) and reason = "Duplicate bases classes" and priority = 6 or not exists(getMro(cls)) and reason = "Failed to compute MRO" and priority = 3 or - exists(int i | failedInference(getBase(cls, i), _, _) and reason = "Failed inference for base class at position " + i) and priority = 5 + exists(int i | + failedInference(getBase(cls, i), _, _) and + reason = "Failed inference for base class at position " + i + ) and + priority = 5 } private int missingBase(ClassObjectInternal cls) { exists(cls.(PythonClassObjectInternal).getScope().getBase(result)) and - not exists(ObjectInternal base | base = getBase(cls, result) and not base = ObjectInternal::unknownClass()) - } - - private predicate duplicateBase(ClassObjectInternal cls) { - exists(int i, int j, ClassObjectInternal dup | - dup = getBase(cls, i) and dup != ObjectInternal::unknownClass() and - dup = getBase(cls, j) and i != j + not exists(ObjectInternal base | + base = getBase(cls, result) and not base = ObjectInternal::unknownClass() ) } - cached boolean improperSubclass(ObjectInternal sub, ObjectInternal sup) { + private predicate duplicateBase(ClassObjectInternal cls) { + exists(int i, int j, ClassObjectInternal dup | + dup = getBase(cls, i) and + dup != ObjectInternal::unknownClass() and + dup = getBase(cls, j) and + i != j + ) + } + + cached + boolean improperSubclass(ObjectInternal sub, ObjectInternal sup) { sub = sup and result = true or result = true and mroContains(Types::getMro(sub), sup) @@ -2093,7 +2396,7 @@ cached module Types { ( n = tpl.length() and result = false or - result = improperSubclass(cls, tpl.getItem(n)).booleanOr(tupleSubclass(cls, tpl, n+1)) + result = improperSubclass(cls, tpl.getItem(n)).booleanOr(tupleSubclass(cls, tpl, n + 1)) ) } @@ -2111,12 +2414,11 @@ cached module Types { exists(ClassObjectInternal cls | Expressions::requireSubClass(cls, sup) and mro = getMro(cls) - ) - and + ) and ( n = mro.length() or - mroDoesnotContain(mro, sup, n+1) and + mroDoesnotContain(mro, sup, n + 1) and mro.getItem(n) != sup and exists(ClassDecl item, ClassDecl sdecl | item = mro.getItem(n).getClassDeclaration() and @@ -2140,7 +2442,8 @@ cached module Types { cls = Builtin::builtin("dict") and sup.isAbstractBaseClass("Iterable") } - cached boolean hasAttr(ObjectInternal cls, string name) { + cached + boolean hasAttr(ObjectInternal cls, string name) { result = mroHasAttr(Types::getMro(cls), name, 0) } @@ -2148,28 +2451,24 @@ cached module Types { exists(ClassObjectInternal cls | Expressions::requireHasAttr(cls, name) and mro = getMro(cls) - ) - and + ) and ( n = mro.length() and result = false or - exists(ClassDecl decl | - decl = mro.getItem(n).getClassDeclaration() | - if decl.declaresAttribute(name) then - result = true - else - result = mroHasAttr(mro, name, n+1) + exists(ClassDecl decl | decl = mro.getItem(n).getClassDeclaration() | + if decl.declaresAttribute(name) + then result = true + else result = mroHasAttr(mro, name, n + 1) ) ) } - } - module AttributePointsTo { - - pragma [noinline] - predicate pointsTo(ControlFlowNode f, Context context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate pointsTo( + ControlFlowNode f, Context context, ObjectInternal value, ControlFlowNode origin + ) { exists(EssaVariable var, string name, CfgOrigin orig | getsVariableAttribute(f, var, name) and variableAttributePointsTo(var, context, name, value, orig) and @@ -2177,15 +2476,17 @@ module AttributePointsTo { ) } - pragma [noinline] + pragma[noinline] private predicate getsVariableAttribute(ControlFlowNode f, EssaVariable var, string name) { Expressions::getattr_call(f, var.getASourceUse(), _, _, name) or f.isLoad() and var.getASourceUse() = f.(AttrNode).getObject(name) } - pragma [nomagic] - predicate variableAttributePointsTo(EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[nomagic] + predicate variableAttributePointsTo( + EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin + ) { definitionAttributePointsTo(var.getDefinition(), context, name, value, origin) or exists(EssaVariable prev | @@ -2194,7 +2495,9 @@ module AttributePointsTo { ) } - predicate definitionAttributePointsTo(EssaDefinition def, Context context, string name, ObjectInternal value, CfgOrigin origin) { + predicate definitionAttributePointsTo( + EssaDefinition def, Context context, string name, ObjectInternal value, CfgOrigin origin + ) { variableAttributePointsTo(def.(PhiFunction).getAnInput(), context, name, value, origin) or piNodeAttributePointsTo(def, context, name, value, origin) @@ -2208,8 +2511,11 @@ module AttributePointsTo { argumentRefinementPointsTo(def, context, name, value, origin) } - pragma [noinline] - private predicate refinementAttributePointsTo(EssaNodeRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate refinementAttributePointsTo( + EssaNodeRefinement def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { attributeAssignmentAttributePointsTo(def, context, name, value, origin) or attributeDeleteAttributePointsTo(def, context, name, value, origin) @@ -2217,10 +2523,12 @@ module AttributePointsTo { uniEdgedPhiAttributePointsTo(def, context, name, value, origin) } - /** Attribute deletions have no effect as far as value tracking is concerned. */ - pragma [noinline] - private predicate attributeAssignmentAttributePointsTo(AttributeAssignment def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attributeAssignmentAttributePointsTo( + AttributeAssignment def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { def.getName() != name and variableAttributePointsTo(def.getInput(), context, name, value, origin) or @@ -2232,41 +2540,60 @@ module AttributePointsTo { } /** Attribute deletions have no effect as far as value tracking is concerned. */ - pragma [noinline] - private predicate attributeDeleteAttributePointsTo(EssaAttributeDeletion def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attributeDeleteAttributePointsTo( + EssaAttributeDeletion def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { def.getName() != name and variableAttributePointsTo(def.getInput(), context, name, value, origin) } - private predicate uniEdgedPhiAttributePointsTo(SingleSuccessorGuard unipi, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate uniEdgedPhiAttributePointsTo( + SingleSuccessorGuard unipi, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { variableAttributePointsTo(unipi.getInput(), context, name, value, origin) } - private predicate piNodeAttributePointsTo(PyEdgeRefinement pi, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate piNodeAttributePointsTo( + PyEdgeRefinement pi, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { variableAttributePointsTo(pi.getInput(), context, name, value, origin) } - private predicate selfParameterAttributePointsTo(ParameterDefinition def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate selfParameterAttributePointsTo( + ParameterDefinition def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { exists(SelfCallsiteRefinement call, Function func, PointsToContext caller | InterProceduralPointsTo::selfMethodCall(call, caller, func, context) and - def.isSelf() and def.getScope() = func and + def.isSelf() and + def.getScope() = func and variableAttributePointsTo(call.getInput(), caller, name, value, origin) ) } /** Pass through for `self` for the implicit re-definition of `self` in `self.foo()`. */ - private predicate selfMethodCallsitePointsTo(SelfCallsiteRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate selfMethodCallsitePointsTo( + SelfCallsiteRefinement def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { /* The value of self remains the same, only the attributes may change */ exists(Function func, PointsToContext callee, EssaVariable exit_self | InterProceduralPointsTo::selfMethodCall(def, context, func, callee) and exit_self.getSourceVariable().(Variable).isSelf() and - exit_self.getScope() = func and + exit_self.getScope() = func and BaseFlow::reaches_exit(exit_self) and variableAttributePointsTo(exit_self, callee, name, value, origin) ) } - private predicate argumentRefinementPointsTo(ArgumentRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate argumentRefinementPointsTo( + ArgumentRefinement def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { exists(ObjectInternal callable | PointsToInternal::pointsTo(def.getCall().getFunction(), context, callable, _) and callable != ObjectInternal::builtin("setattr") @@ -2274,21 +2601,22 @@ module AttributePointsTo { variableAttributePointsTo(def.getInput(), context, name, value, origin) or exists(string othername | - Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), othername, _, _) and + Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), othername, + _, _) and not othername = name ) and variableAttributePointsTo(def.getInput(), context, name, value, origin) or exists(ControlFlowNode orig | - Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), name, value, orig) and + Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), name, value, + orig) and origin = CfgOrigin::fromCfgNode(orig) ) } - } -cached module ModuleAttributes { - +cached +module ModuleAttributes { private EssaVariable varAtExit(Module mod, string name) { result.getName() = name and result.getAUse() = mod.getANormalExit() } @@ -2301,15 +2629,17 @@ cached module ModuleAttributes { result = moduleStateVariable(mod.getANormalExit()) } - cached predicate pointsToAtExit(Module mod, string name, ObjectInternal value, CfgOrigin origin) { - if exists(varAtExit(mod, name)) then ( - PointsToInternal::variablePointsTo(varAtExit(mod, name), any(Context c | c.isImport()), value, origin) - ) else ( - attributePointsTo(moduleStateVarAtExit(mod), name, value, origin) - ) + cached + predicate pointsToAtExit(Module mod, string name, ObjectInternal value, CfgOrigin origin) { + if exists(varAtExit(mod, name)) + then + PointsToInternal::variablePointsTo(varAtExit(mod, name), any(Context c | c.isImport()), value, + origin) + else attributePointsTo(moduleStateVarAtExit(mod), name, value, origin) } - cached predicate attributePointsTo(EssaVariable var, string name, ObjectInternal value, CfgOrigin origin) { + cached + predicate attributePointsTo(EssaVariable var, string name, ObjectInternal value, CfgOrigin origin) { importStarPointsTo(var.getDefinition(), name, value, origin) or callsitePointsTo(var.getDefinition(), name, value, origin) @@ -2320,7 +2650,7 @@ cached module ModuleAttributes { } /** Holds if the phi-function `phi` refers to `(value, origin)` given the context `context`. */ - pragma [nomagic] + pragma[nomagic] private predicate phiPointsTo(PhiFunction phi, string name, ObjectInternal value, CfgOrigin origin) { exists(EssaVariable input | PointsToInternal::ssa_phi_reachable_from_input(phi, any(Context c | c.isImport()), input) and @@ -2328,17 +2658,19 @@ cached module ModuleAttributes { ) } - pragma [nomagic] - private predicate importStarPointsTo(ImportStarRefinement def, string name, ObjectInternal value, CfgOrigin origin) { + pragma[nomagic] + private predicate importStarPointsTo( + ImportStarRefinement def, string name, ObjectInternal value, CfgOrigin origin + ) { def.getVariable().isMetaVariable() and /* Attribute from imported module */ exists(ModuleObjectInternal mod | - importStarDef(def, _, mod) - and + importStarDef(def, _, mod) and /* Attribute from imported module */ exists(CfgOrigin orig | InterModulePointsTo::moduleExportsBoolean(mod, name) = true and - mod.attribute(name, value, orig) and origin = orig.fix(def.getDefiningNode()) and + mod.attribute(name, value, orig) and + origin = orig.fix(def.getDefiningNode()) and not exists(Variable v | v.getId() = name and v.getScope() = def.getScope()) ) ) @@ -2351,19 +2683,26 @@ cached module ModuleAttributes { ) } - private predicate importStarDef(ImportStarRefinement def, EssaVariable input, ModuleObjectInternal mod) { + private predicate importStarDef( + ImportStarRefinement def, EssaVariable input, ModuleObjectInternal mod + ) { exists(ImportStarNode imp | - def.getVariable().getName() = "$" and imp = def.getDefiningNode() and - input = def.getInput() and PointsToInternal::importCtxPointsTo(imp.getModule(), mod, _) + def.getVariable().getName() = "$" and + imp = def.getDefiningNode() and + input = def.getInput() and + PointsToInternal::importCtxPointsTo(imp.getModule(), mod, _) ) } - /** Points-to for a variable (possibly) redefined by a call: + /** + * Points-to for a variable (possibly) redefined by a call: * `var = ...; foo(); use(var)` * Where var may be redefined in call to `foo` if `var` escapes (is global or non-local). */ - pragma [noinline] - private predicate callsitePointsTo(CallsiteRefinement def, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate callsitePointsTo( + CallsiteRefinement def, string name, ObjectInternal value, CfgOrigin origin + ) { def.getVariable().isMetaVariable() and exists(EssaVariable var, Function func, PointsToContext callee | InterProceduralPointsTo::callsite_calls_function(def.getCall(), _, func, callee, _) and @@ -2372,18 +2711,21 @@ cached module ModuleAttributes { ) } - /** Holds if the attribute name of the implicit '$' variable refers to `value` at the start of the scope. + /** + * Holds if the attribute name of the implicit '$' variable refers to `value` at the start of the scope. * Since it cannot refer to any actual value, it is set to "undefined" for sub module names. */ - pragma [noinline] - private predicate scopeEntryPointsTo(ScopeEntryDefinition def, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate scopeEntryPointsTo( + ScopeEntryDefinition def, string name, ObjectInternal value, CfgOrigin origin + ) { def.getVariable().isMetaVariable() and exists(Module m | def.getScope() = m and not exists(EssaVariable named | named.getName() = name and named.getScope() = m) and value = ObjectInternal::undefined() and origin = CfgOrigin::unknown() - | + | m.isPackageInit() and exists(m.getPackage().getSubModule(name)) or not m.declaredInAll(_) and @@ -2393,6 +2735,4 @@ cached module ModuleAttributes { ) ) } - } - diff --git a/python/ql/src/semmle/python/pointsto/PointsToContext.qll b/python/ql/src/semmle/python/pointsto/PointsToContext.qll index 8804a51f9cb..a82a62130b2 100644 --- a/python/ql/src/semmle/python/pointsto/PointsToContext.qll +++ b/python/ql/src/semmle/python/pointsto/PointsToContext.qll @@ -1,6 +1,7 @@ import python private import semmle.python.pointsto.PointsTo private import semmle.python.objects.ObjectInternal + /* * A note on 'cost'. Cost doesn't represent the cost to compute, * but (a vague estimate of) the cost to compute per value gained. @@ -14,7 +15,7 @@ private int given_cost() { ) } -pragma [noinline] +pragma[noinline] private int max_context_cost() { not py_flags_versioned("context.cost", _, _) and result = 7 or @@ -22,13 +23,13 @@ private int max_context_cost() { } private int syntactic_call_count(Scope s) { - exists(Function f | - f = s and f.getName() != "__init__" | - result = count(CallNode call | - call.getFunction().(NameNode).getId() = f.getName() - or - call.getFunction().(AttrNode).getName() = f.getName() - ) + exists(Function f | f = s and f.getName() != "__init__" | + result = + count(CallNode call | + call.getFunction().(NameNode).getId() = f.getName() + or + call.getFunction().(AttrNode).getName() = f.getName() + ) ) or s.getName() = "__init__" and result = 1 @@ -37,11 +38,13 @@ private int syntactic_call_count(Scope s) { } private int incoming_call_cost(Scope s) { - /* Syntactic call count will often be a considerable overestimate + /* + * Syntactic call count will often be a considerable overestimate * of the actual number of calls, so we use the square root. * Cost = log(sqrt(call-count)) */ - result = ((syntactic_call_count(s)+1).log(2)*0.5).floor() + + result = ((syntactic_call_count(s) + 1).log(2) * 0.5).floor() } private int context_cost(TPointsToContext ctx) { @@ -55,15 +58,10 @@ private int context_cost(TPointsToContext ctx) { } private int call_cost(CallNode call) { - if call.getScope().inSource() then - result = 2 - else - result = 3 + if call.getScope().inSource() then result = 2 else result = 3 } -private int outgoing_calls(Scope s) { - result = strictcount(CallNode call | call.getScope() = s) -} +private int outgoing_calls(Scope s) { result = strictcount(CallNode call | call.getScope() = s) } predicate super_method_call(CallNode call) { call.getFunction().(AttrNode).getObject().(CallNode).getFunction().(NameNode).getId() = "super" @@ -74,74 +72,65 @@ private int outgoing_call_cost(CallNode c) { result = outgoing_calls(c.getScope()).log(2).floor() } -/** Cost of contexts for a call, the more callers the +/** + * Cost of contexts for a call, the more callers the * callee of call has the more expensive it is to add contexts for it. * This seems to be an effective heuristics for preventing an explosion * in the number of contexts while retaining good results. */ private int splay_cost(CallNode c) { - if super_method_call(c) then - result = 0 - else - result = outgoing_call_cost(c) + incoming_call_cost(c.getScope()) + if super_method_call(c) + then result = 0 + else result = outgoing_call_cost(c) + incoming_call_cost(c.getScope()) } private predicate call_to_init_or_del(CallNode call) { - exists(string mname | - mname = "__init__" or mname = "__del__" | + exists(string mname | mname = "__init__" or mname = "__del__" | mname = call.getFunction().(AttrNode).getName() ) } /** Total cost estimate */ private int total_call_cost(CallNode call) { - /* We want to always follow __init__ and __del__ calls as they tell us about object construction, + /* + * We want to always follow __init__ and __del__ calls as they tell us about object construction, * but we need to be aware of cycles, so they must have a non-zero cost. */ - if call_to_init_or_del(call) then - result = 1 - else - result = call_cost(call) + splay_cost(call) + + if call_to_init_or_del(call) then result = 1 else result = call_cost(call) + splay_cost(call) } -pragma [noinline] +pragma[noinline] private int total_cost(CallNode call, PointsToContext ctx) { ctx.appliesTo(call) and result = total_call_cost(call) + context_cost(ctx) } -private cached newtype TPointsToContext = - TMainContext() - or - TRuntimeContext() - or - TImportContext() - or +cached +private newtype TPointsToContext = + TMainContext() or + TRuntimeContext() or + TImportContext() or TCallContext(ControlFlowNode call, PointsToContext outerContext, int cost) { total_cost(call, outerContext) = cost and cost <= max_context_cost() - } - or + } or TObjectContext(SelfInstanceInternal object) module Context { - - PointsToContext forObject(ObjectInternal object) { - result = TObjectContext(object) - } - + PointsToContext forObject(ObjectInternal object) { result = TObjectContext(object) } } - -/** Points-to context. Context can be one of: +/** + * Points-to context. Context can be one of: * * "main": Used for scripts. * * "import": Use for non-script modules. * * "default": Use for functions and methods without caller context. * * All other contexts are call contexts and consist of a pair of call-site and caller context. */ class PointsToContext extends TPointsToContext { - - cached string toString() { + cached + string toString() { this = TMainContext() and result = "main" or this = TRuntimeContext() and result = "runtime" @@ -166,10 +155,8 @@ class PointsToContext extends TPointsToContext { this = TCallContext(call, caller, _) } - /** Gets the caller context for this callee context. */ - PointsToContext getOuter() { - this = TCallContext(_, result, _) - } + /** Gets the caller context for this callee context. */ + PointsToContext getOuter() { this = TCallContext(_, result, _) } /** Holds if this context is relevant to the given scope. */ predicate appliesToScope(Scope s) { @@ -182,9 +169,12 @@ class PointsToContext extends TPointsToContext { this = TRuntimeContext() and executes_in_runtime_context(s) or /* Called functions, regardless of their name */ - exists(PythonFunctionObjectInternal callable, ControlFlowNode call, TPointsToContext outerContext | + exists( + PythonFunctionObjectInternal callable, ControlFlowNode call, TPointsToContext outerContext + | call = callable.getACall(outerContext) and - this = TCallContext(call, outerContext, _) | + this = TCallContext(call, outerContext, _) + | s = callable.getScope() ) or @@ -192,30 +182,20 @@ class PointsToContext extends TPointsToContext { } /** Holds if this context can apply to the CFG node `n`. */ - pragma [inline] - predicate appliesTo(ControlFlowNode n) { - this.appliesToScope(n.getScope()) - } + pragma[inline] + predicate appliesTo(ControlFlowNode n) { this.appliesToScope(n.getScope()) } /** Holds if this context is a call context. */ - predicate isCall() { - this = TCallContext(_, _, _) - } + predicate isCall() { this = TCallContext(_, _, _) } /** Holds if this is the "main" context. */ - predicate isMain() { - this = TMainContext() - } + predicate isMain() { this = TMainContext() } /** Holds if this is the "import" context. */ - predicate isImport() { - this = TImportContext() - } + predicate isImport() { this = TImportContext() } /** Holds if this is the "default" context. */ - predicate isRuntime() { - this = TRuntimeContext() - } + predicate isRuntime() { this = TRuntimeContext() } /** Holds if this context or one of its caller contexts is the default context. */ predicate fromRuntime() { @@ -231,19 +211,13 @@ class PointsToContext extends TPointsToContext { result = this.getOuter().getDepth() + 1 } - int getCost() { - result = context_cost(this) - } + int getCost() { result = context_cost(this) } - CallNode getCall() { - this = TCallContext(result, _, _) - } + CallNode getCall() { this = TCallContext(result, _, _) } /** Holds if a call would be too expensive to create a new context for */ - pragma [nomagic] - predicate untrackableCall(CallNode call) { - total_cost(call, this) > max_context_cost() - } + pragma[nomagic] + predicate untrackableCall(CallNode call) { total_cost(call, this) > max_context_cost() } CallNode getRootCall() { this = TCallContext(result, TImportContext(), _) @@ -252,35 +226,30 @@ class PointsToContext extends TPointsToContext { } /** Gets a version of Python that this context includes */ - pragma [inline] + pragma[inline] Version getAVersion() { /* Currently contexts do not include any version information, but may do in the future */ result = major_version() } - } -private predicate in_source(Scope s) { - exists(s.getEnclosingModule().getFile().getRelativePath()) -} +private predicate in_source(Scope s) { exists(s.getEnclosingModule().getFile().getRelativePath()) } -/** Holds if this scope can be executed in the default context. +/** + * Holds if this scope can be executed in the default context. * All modules and classes executed at import time and * all "public" functions and methods, including those invoked by the VM. */ predicate executes_in_runtime_context(Function f) { /* "Public" scope, i.e. functions whose name starts not with an underscore, or special methods */ - (f.getName().charAt(0) != "_" or f.isSpecialMethod() or f.isInitMethod()) - and + (f.getName().charAt(0) != "_" or f.isSpecialMethod() or f.isInitMethod()) and in_source(f) } private predicate maybe_main(Module m) { - exists(If i, Compare cmp, Name name, StrConst main | - m.getAStmt() = i and i.getTest() = cmp | + exists(If i, Compare cmp, Name name, StrConst main | m.getAStmt() = i and i.getTest() = cmp | cmp.compares(name, any(Eq eq), main) and name.getId() = "__name__" and main.getText() = "__main__" ) } - From 51f1cf020c4f46ac762e96c9eab8203fa66b5ec0 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:36:48 +0100 Subject: [PATCH 111/459] Python: Autoformat `security`. --- .../src/semmle/python/security/ClearText.qll | 22 ++-- .../ql/src/semmle/python/security/Crypto.qll | 104 ++++-------------- .../src/semmle/python/security/Exceptions.qll | 64 +++-------- .../ql/src/semmle/python/security/Paths.qll | 4 - python/ql/src/semmle/python/security/SQL.qll | 2 +- .../semmle/python/security/SensitiveData.qll | 57 +++------- .../semmle/python/security/TaintTracking.qll | 1 + .../semmle/python/security/flow/AnyCall.qll | 10 +- .../python/security/injection/Command.qll | 50 +++------ .../security/injection/Deserialization.qll | 8 +- .../semmle/python/security/injection/Exec.qll | 20 ++-- .../python/security/injection/Marshal.qll | 24 ++-- .../semmle/python/security/injection/Path.qll | 54 +++------ .../python/security/injection/Pickle.qll | 17 +-- .../semmle/python/security/injection/Sql.qll | 49 +++------ .../semmle/python/security/injection/Xml.qll | 55 +++------ .../semmle/python/security/injection/Yaml.qll | 16 +-- .../semmle/python/security/strings/Basic.qll | 54 +++++---- .../semmle/python/security/strings/Common.qll | 4 +- .../python/security/strings/External.qll | 9 +- .../python/security/strings/Untrusted.qll | 10 +- 21 files changed, 186 insertions(+), 448 deletions(-) diff --git a/python/ql/src/semmle/python/security/ClearText.qll b/python/ql/src/semmle/python/security/ClearText.qll index ea4c33b7a9f..d08d2b03883 100644 --- a/python/ql/src/semmle/python/security/ClearText.qll +++ b/python/ql/src/semmle/python/security/ClearText.qll @@ -5,17 +5,12 @@ import semmle.python.dataflow.Files import semmle.python.web.Http module ClearTextStorage { - abstract class Sink extends TaintSink { - override predicate sinks(TaintKind kind) { - kind instanceof SensitiveData - } + override predicate sinks(TaintKind kind) { kind instanceof SensitiveData } } class CookieStorageSink extends Sink { - CookieStorageSink() { - any(CookieSet cookie).getValue() = this - } + CookieStorageSink() { any(CookieSet cookie).getValue() = this } } class FileStorageSink extends Sink { @@ -23,20 +18,17 @@ module ClearTextStorage { exists(CallNode call, AttrNode meth, string name | any(OpenFile fd).taints(meth.getObject(name)) and call.getFunction() = meth and - call.getAnArg() = this | + call.getAnArg() = this + | name = "write" ) } } - } module ClearTextLogging { - abstract class Sink extends TaintSink { - override predicate sinks(TaintKind kind) { - kind instanceof SensitiveData - } + override predicate sinks(TaintKind kind) { kind instanceof SensitiveData } } class PrintSink extends Sink { @@ -53,7 +45,8 @@ module ClearTextLogging { exists(CallNode call, AttrNode meth, string name | call.getFunction() = meth and meth.getObject(name).(NameNode).getId().matches("logg%") and - call.getAnArg() = this | + call.getAnArg() = this + | name = "error" or name = "warn" or name = "warning" or @@ -62,5 +55,4 @@ module ClearTextLogging { ) } } - } diff --git a/python/ql/src/semmle/python/security/Crypto.qll b/python/ql/src/semmle/python/security/Crypto.qll index 4a04b2082c6..06244851018 100644 --- a/python/ql/src/semmle/python/security/Crypto.qll +++ b/python/ql/src/semmle/python/security/Crypto.qll @@ -1,49 +1,32 @@ import python import semmle.python.security.TaintTracking - private import semmle.python.security.SensitiveData private import semmle.crypto.Crypto as CryptoLib - abstract class WeakCryptoSink extends TaintSink { - - override predicate sinks(TaintKind taint) { - taint instanceof SensitiveData - } + override predicate sinks(TaintKind taint) { taint instanceof SensitiveData } } /** Modeling the 'pycrypto' package https://github.com/dlitz/pycrypto (latest release 2013) */ module Pycrypto { - - ModuleValue cipher(string name) { - result = Module::named("Crypto.Cipher").attr(name) - } + ModuleValue cipher(string name) { result = Module::named("Crypto.Cipher").attr(name) } class CipherInstance extends TaintKind { - string name; CipherInstance() { - this = "Crypto.Cipher." + name and + this = "Crypto.Cipher." + name and exists(cipher(name)) } - string getName() { - result = name - } + string getName() { result = name } - CryptoLib::CryptographicAlgorithm getAlgorithm() { - result.getName() = name - } - - predicate isWeak() { - this.getAlgorithm().isWeak() - } + CryptoLib::CryptographicAlgorithm getAlgorithm() { result.getName() = name } + predicate isWeak() { this.getAlgorithm().isWeak() } } class CipherInstanceSource extends TaintSource { - CipherInstance instance; CipherInstanceSource() { @@ -53,18 +36,12 @@ module Pycrypto { ) } - override string toString() { - result = "Source of " + instance - } - - override predicate isSourceOf(TaintKind kind) { - kind = instance - } + override string toString() { result = "Source of " + instance } + override predicate isSourceOf(TaintKind kind) { kind = instance } } class PycryptoWeakCryptoSink extends WeakCryptoSink { - string name; PycryptoWeakCryptoSink() { @@ -77,36 +54,24 @@ module Pycrypto { ) } - override string toString() { - result = "Use of weak crypto algorithm " + name - } - + override string toString() { result = "Use of weak crypto algorithm " + name } } - } module Cryptography { - ModuleValue ciphers() { result = Module::named("cryptography.hazmat.primitives.ciphers") and result.isPackage() } class CipherClass extends ClassValue { - CipherClass() { - ciphers().attr("Cipher") = this - } + CipherClass() { ciphers().attr("Cipher") = this } } class AlgorithmClass extends ClassValue { + AlgorithmClass() { ciphers().attr("algorithms").attr(_) = this } - AlgorithmClass() { - ciphers().attr("algorithms").attr(_) = this - } - - string getAlgorithmName() { - result = this.declaredAttribute("name").(StringValue).getText() - } + string getAlgorithmName() { result = this.declaredAttribute("name").(StringValue).getText() } predicate isWeak() { exists(CryptoLib::CryptographicAlgorithm algo | @@ -117,61 +82,39 @@ module Cryptography { } class CipherInstance extends TaintKind { - AlgorithmClass cls; - CipherInstance() { - this = "cryptography.Cipher." + cls.getAlgorithmName() - } + CipherInstance() { this = "cryptography.Cipher." + cls.getAlgorithmName() } - AlgorithmClass getAlgorithm() { - result = cls - } + AlgorithmClass getAlgorithm() { result = cls } - predicate isWeak() { - cls.isWeak() - } + predicate isWeak() { cls.isWeak() } override TaintKind getTaintOfMethodResult(string name) { name = "encryptor" and result.(Encryptor).getAlgorithm() = this.getAlgorithm() } - } class CipherSource extends TaintSource { - - CipherSource() { - this.(CallNode).getFunction().pointsTo(any(CipherClass cls)) - } + CipherSource() { this.(CallNode).getFunction().pointsTo(any(CipherClass cls)) } override predicate isSourceOf(TaintKind kind) { this.(CallNode).getArg(0).pointsTo().getClass() = kind.(CipherInstance).getAlgorithm() } - override string toString() { - result = "cryptography.Cipher.source" - } - + override string toString() { result = "cryptography.Cipher.source" } } class Encryptor extends TaintKind { - AlgorithmClass cls; - Encryptor() { - this = "cryptography.encryptor." + cls.getAlgorithmName() - - } - - AlgorithmClass getAlgorithm() { - result = cls - } + Encryptor() { this = "cryptography.encryptor." + cls.getAlgorithmName() } + AlgorithmClass getAlgorithm() { result = cls } } class CryptographyWeakCryptoSink extends WeakCryptoSink { - CryptographyWeakCryptoSink() { exists(CallNode call, AttrNode method, Encryptor encryptor | call.getAnArg() = this and @@ -181,17 +124,11 @@ module Cryptography { ) } - override string toString() { - result = "Use of weak crypto algorithm" - } - + override string toString() { result = "Use of weak crypto algorithm" } } - - } private class CipherConfig extends TaintTracking::Configuration { - CipherConfig() { this = "Crypto cipher config" } override predicate isSource(TaintTracking::Source source) { @@ -199,5 +136,4 @@ private class CipherConfig extends TaintTracking::Configuration { or source instanceof Cryptography::CipherSource } - } diff --git a/python/ql/src/semmle/python/security/Exceptions.qll b/python/ql/src/semmle/python/security/Exceptions.qll index 143cf494bba..5344808caac 100644 --- a/python/ql/src/semmle/python/security/Exceptions.qll +++ b/python/ql/src/semmle/python/security/Exceptions.qll @@ -7,43 +7,31 @@ import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Basic -private Value traceback_function(string name) { - result = Module::named("traceback").attr(name) -} +private Value traceback_function(string name) { result = Module::named("traceback").attr(name) } /** * This represents information relating to an exception, for instance the * message, arguments or parts of the exception traceback. */ class ExceptionInfo extends StringKind { + ExceptionInfo() { this = "exception.info" } - ExceptionInfo() { - this = "exception.info" - } - - override string repr() { - result = "exception info" - } - + override string repr() { result = "exception info" } } -/** A class representing sources of information about +/** + * A class representing sources of information about * execution state exposed in tracebacks and the like. */ -abstract class ErrorInfoSource extends TaintSource {} +abstract class ErrorInfoSource extends TaintSource { } /** * This kind represents exceptions themselves. */ class ExceptionKind extends TaintKind { + ExceptionKind() { this = "exception.kind" } - ExceptionKind() { - this = "exception.kind" - } - - override string repr() { - result = "exception" - } + override string repr() { result = "exception" } override TaintKind getTaintOfAttribute(string name) { name = "args" and result instanceof ExceptionInfoSequence @@ -57,7 +45,6 @@ class ExceptionKind extends TaintKind { * `except` statement. */ class ExceptionSource extends ErrorInfoSource { - ExceptionSource() { exists(ClassValue cls | cls.getASuperType() = ClassValue::baseException() and @@ -67,13 +54,9 @@ class ExceptionSource extends ErrorInfoSource { this = any(ExceptStmt s).getName().getAFlowNode() } - override string toString() { - result = "exception.source" - } + override string toString() { result = "exception.source" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionKind - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionKind } } /** @@ -81,18 +64,14 @@ class ExceptionSource extends ErrorInfoSource { * for instance the contents of the `args` attribute, or the stack trace. */ class ExceptionInfoSequence extends SequenceKind { - ExceptionInfoSequence() { - this.getItem() instanceof ExceptionInfo - } + ExceptionInfoSequence() { this.getItem() instanceof ExceptionInfo } } - /** * Represents calls to functions in the `traceback` module that return * sequences of exception information. */ class CallToTracebackFunction extends ErrorInfoSource { - CallToTracebackFunction() { exists(string name | name = "extract_tb" or @@ -107,13 +86,9 @@ class CallToTracebackFunction extends ErrorInfoSource { ) } - override string toString() { - result = "exception.info.sequence.source" - } + override string toString() { result = "exception.info.sequence.source" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionInfoSequence - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfoSequence } } /** @@ -121,16 +96,9 @@ class CallToTracebackFunction extends ErrorInfoSource { * string of information about an exception. */ class FormattedTracebackSource extends ErrorInfoSource { + FormattedTracebackSource() { this = traceback_function("format_exc").getACall() } - FormattedTracebackSource() { - this = traceback_function("format_exc").getACall() - } + override string toString() { result = "exception.info.source" } - override string toString() { - result = "exception.info.source" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionInfo - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfo } } diff --git a/python/ql/src/semmle/python/security/Paths.qll b/python/ql/src/semmle/python/security/Paths.qll index 846425ebca3..3c7bc657948 100644 --- a/python/ql/src/semmle/python/security/Paths.qll +++ b/python/ql/src/semmle/python/security/Paths.qll @@ -1,8 +1,6 @@ import semmle.python.dataflow.Implementation module TaintTrackingPaths { - - predicate edge(TaintTrackingNode src, TaintTrackingNode dest, string label) { exists(TaintTrackingNode source, TaintTrackingNode sink | source.getConfiguration().hasFlowPath(source, sink) and @@ -11,10 +9,8 @@ module TaintTrackingPaths { dest.getASuccessor*() = sink ) } - } - query predicate edges(TaintTrackingNode fromnode, TaintTrackingNode tonode) { TaintTrackingPaths::edge(fromnode, tonode, _) } diff --git a/python/ql/src/semmle/python/security/SQL.qll b/python/ql/src/semmle/python/security/SQL.qll index d1940ff05f5..a09d74134e6 100644 --- a/python/ql/src/semmle/python/security/SQL.qll +++ b/python/ql/src/semmle/python/security/SQL.qll @@ -1,4 +1,4 @@ import python import semmle.python.security.TaintTracking -abstract class SqlInjectionSink extends TaintSink {} +abstract class SqlInjectionSink extends TaintSink { } diff --git a/python/ql/src/semmle/python/security/SensitiveData.qll b/python/ql/src/semmle/python/security/SensitiveData.qll index 15b4c40f239..6e0b44d3c33 100644 --- a/python/ql/src/semmle/python/security/SensitiveData.qll +++ b/python/ql/src/semmle/python/security/SensitiveData.qll @@ -20,7 +20,6 @@ import semmle.python.web.HttpRequest * This is copied from the javascript library, but should be language independent. */ private module HeuristicNames { - /** * Gets a regular expression that identifies strings that may indicate the presence of secret * or trusted data. @@ -32,8 +31,8 @@ private module HeuristicNames { * user names or other account information. */ string maybeAccountInfo() { - result = "(?is).*acc(ou)?nt.*" or - result = "(?is).*(puid|username|userid).*" + result = "(?is).*acc(ou)?nt.*" or + result = "(?is).*(puid|username|userid).*" } /** @@ -41,8 +40,8 @@ private module HeuristicNames { * a password or an authorization key. */ string maybePassword() { - result = "(?is).*pass(wd|word|code|phrase)(?!.*question).*" or - result = "(?is).*(auth(entication|ori[sz]ation)?)key.*" + result = "(?is).*pass(wd|word|code|phrase)(?!.*question).*" or + result = "(?is).*(auth(entication|ori[sz]ation)?)key.*" } /** @@ -51,7 +50,7 @@ private module HeuristicNames { */ string maybeCertificate() { result = "(?is).*(cert)(?!.*(format|name)).*" } - /** + /** * Gets a regular expression that identifies strings that may indicate the presence * of sensitive data, with `classification` describing the kind of sensitive data involved. */ @@ -78,35 +77,35 @@ private module HeuristicNames { name.regexpMatch(HeuristicNames::maybeSensitive(result)) and not name.regexpMatch(HeuristicNames::notSensitive()) } - } abstract class SensitiveData extends TaintKind { - bindingset[this] SensitiveData() { this = this } - } module SensitiveData { - class Secret extends SensitiveData { Secret() { this = "sensitive.data.secret" } + override string repr() { result = "a secret" } } class Id extends SensitiveData { Id() { this = "sensitive.data.id" } + override string repr() { result = "an ID" } } class Password extends SensitiveData { Password() { this = "sensitive.data.password" } + override string repr() { result = "a password" } } class Certificate extends SensitiveData { Certificate() { this = "sensitive.data.certificate" } + override string repr() { result = "a certificate or key" } } @@ -115,53 +114,35 @@ module SensitiveData { } abstract class Source extends TaintSource { - abstract string repr(); - } private class SensitiveCallSource extends Source { - SensitiveData data; SensitiveCallSource() { - exists(Value callee | - callee.getACall() = this | - data = fromFunction(callee) - ) + exists(Value callee | callee.getACall() = this | data = fromFunction(callee)) } - override predicate isSourceOf(TaintKind kind) { - kind = data - } - - override string repr() { - result = "a call returning " + data.repr() - } + override predicate isSourceOf(TaintKind kind) { kind = data } + override string repr() { result = "a call returning " + data.repr() } } /** An access to a variable or property that might contain sensitive data. */ private class SensitiveVariableAccess extends SensitiveData::Source { - SensitiveData data; SensitiveVariableAccess() { data = HeuristicNames::getSensitiveDataForName(this.(AttrNode).getName()) } - override predicate isSourceOf(TaintKind kind) { - kind = data - } - - override string repr() { - result = "an attribute or property containing " + data.repr() - } + override predicate isSourceOf(TaintKind kind) { kind = data } + override string repr() { result = "an attribute or property containing " + data.repr() } } private class SensitiveRequestParameter extends SensitiveData::Source { - SensitiveData data; SensitiveRequestParameter() { @@ -172,16 +153,10 @@ module SensitiveData { ) } - override predicate isSourceOf(TaintKind kind) { - kind = data - } - - override string repr() { - result = "a request parameter containing " + data.repr() - } + override predicate isSourceOf(TaintKind kind) { kind = data } + override string repr() { result = "a request parameter containing " + data.repr() } } - } //Backwards compatibility diff --git a/python/ql/src/semmle/python/security/TaintTracking.qll b/python/ql/src/semmle/python/security/TaintTracking.qll index c0bcbb6acb5..290fcc1ca71 100755 --- a/python/ql/src/semmle/python/security/TaintTracking.qll +++ b/python/ql/src/semmle/python/security/TaintTracking.qll @@ -1,2 +1,3 @@ /** For backwards compatibility */ + import semmle.python.dataflow.TaintTracking diff --git a/python/ql/src/semmle/python/security/flow/AnyCall.qll b/python/ql/src/semmle/python/security/flow/AnyCall.qll index 7a766bf25a5..de9526daf21 100644 --- a/python/ql/src/semmle/python/security/flow/AnyCall.qll +++ b/python/ql/src/semmle/python/security/flow/AnyCall.qll @@ -3,13 +3,7 @@ import semmle.python.security.strings.Basic /** Assume that taint flows from argument to result for *any* call */ class AnyCallStringFlow extends DataFlowExtension::DataFlowNode { + AnyCallStringFlow() { any(CallNode call).getAnArg() = this } - AnyCallStringFlow() { - any(CallNode call).getAnArg() = this - } - - override ControlFlowNode getASuccessorNode() { - result.(CallNode).getAnArg() = this - } - + override ControlFlowNode getASuccessorNode() { result.(CallNode).getAnArg() = this } } diff --git a/python/ql/src/semmle/python/security/injection/Command.qll b/python/ql/src/semmle/python/security/injection/Command.qll index 7efcd382a3c..dcc9813db10 100644 --- a/python/ql/src/semmle/python/security/injection/Command.qll +++ b/python/ql/src/semmle/python/security/injection/Command.qll @@ -1,26 +1,24 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious OS commands. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted - private ModuleObject osOrPopenModule() { result.getName() = "os" or result.getName() = "popen2" } private Object makeOsCall() { - exists(string name | - result = ModuleObject::named("subprocess").attr(name) | + exists(string name | result = ModuleObject::named("subprocess").attr(name) | name = "Popen" or - name = "call" or + name = "call" or name = "check_call" or name = "check_output" or name = "run" @@ -29,40 +27,27 @@ private Object makeOsCall() { /**Special case for first element in sequence. */ class FirstElementKind extends TaintKind { + FirstElementKind() { this = "sequence[" + any(ExternalStringKind key) + "][0]" } - FirstElementKind() { - this = "sequence[" + any(ExternalStringKind key) + "][0]" - } - - override string repr() { - result = "first item in sequence of " + this.getItem().repr() - } + override string repr() { result = "first item in sequence of " + this.getItem().repr() } /** Gets the taint kind for item in this sequence. */ - ExternalStringKind getItem() { - this = "sequence[" + result + "][0]" - } - + ExternalStringKind getItem() { this = "sequence[" + result + "][0]" } } class FirstElementFlow extends DataFlowExtension::DataFlowNode { + FirstElementFlow() { this = any(SequenceNode s).getElement(0) } - FirstElementFlow() { - this = any(SequenceNode s).getElement(0) - } - - override - ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) { + override ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) { result.(SequenceNode).getElement(0) = this and tokind.(FirstElementKind).getItem() = fromkind } - } -/** A taint sink that is potentially vulnerable to malicious shell commands. +/** + * A taint sink that is potentially vulnerable to malicious shell commands. * The `vuln` in `subprocess.call(shell=vuln)` and similar calls. */ class ShellCommand extends TaintSink { - override string toString() { result = "shell command" } ShellCommand() { @@ -75,7 +60,8 @@ class ShellCommand extends TaintSink { or exists(CallNode call, string name | call.getAnArg() = this and - call.getFunction().refersTo(osOrPopenModule().attr(name)) | + call.getFunction().refersTo(osOrPopenModule().attr(name)) + | name = "system" or name = "popen" or name.matches("popen_") @@ -94,19 +80,18 @@ class ShellCommand extends TaintSink { /* List (or tuple) containing a tainted string command */ kind instanceof ExternalStringSequenceKind } - } -/** A taint sink that is potentially vulnerable to malicious shell commands. +/** + * A taint sink that is potentially vulnerable to malicious shell commands. * The `vuln` in `subprocess.call(vuln, ...)` and similar calls. */ class OsCommandFirstArgument extends TaintSink { - override string toString() { result = "OS command first argument" } OsCommandFirstArgument() { not this instanceof ShellCommand and - exists(CallNode call| + exists(CallNode call | call.getFunction().refersTo(makeOsCall()) and call.getArg(0) = this ) @@ -119,5 +104,4 @@ class OsCommandFirstArgument extends TaintSink { /* List (or tuple) whose first element is tainted */ kind instanceof FirstElementKind } - } diff --git a/python/ql/src/semmle/python/security/injection/Deserialization.qll b/python/ql/src/semmle/python/security/injection/Deserialization.qll index 8d15ef2f8ac..14bf9d2233d 100644 --- a/python/ql/src/semmle/python/security/injection/Deserialization.qll +++ b/python/ql/src/semmle/python/security/injection/Deserialization.qll @@ -1,14 +1,8 @@ - import python import semmle.python.security.TaintTracking - /** `pickle.loads(untrusted)` vulnerability. */ abstract class DeserializationSink extends TaintSink { - bindingset[this] - DeserializationSink() { - this = this - } - + DeserializationSink() { this = this } } diff --git a/python/ql/src/semmle/python/security/injection/Exec.qll b/python/ql/src/semmle/python/security/injection/Exec.qll index 3830bbbd611..ee1621981c0 100644 --- a/python/ql/src/semmle/python/security/injection/Exec.qll +++ b/python/ql/src/semmle/python/security/injection/Exec.qll @@ -1,33 +1,30 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious Python code. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted - private FunctionObject exec_or_eval() { result = Object::builtin("exec") or result = Object::builtin("eval") } -/** A taint sink that represents an argument to exec or eval that is vulnerable to malicious input. +/** + * A taint sink that represents an argument to exec or eval that is vulnerable to malicious input. * The `vuln` in `exec(vuln)` or similar. */ class StringEvaluationNode extends TaintSink { - override string toString() { result = "exec or eval" } StringEvaluationNode() { - exists(Exec exec | - exec.getASubExpression().getAFlowNode() = this - ) + exists(Exec exec | exec.getASubExpression().getAFlowNode() = this) or exists(CallNode call | exec_or_eval().getACall() = call and @@ -35,8 +32,5 @@ class StringEvaluationNode extends TaintSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/injection/Marshal.qll b/python/ql/src/semmle/python/security/injection/Marshal.qll index 5ba361b1d94..274392c8b4f 100644 --- a/python/ql/src/semmle/python/security/injection/Marshal.qll +++ b/python/ql/src/semmle/python/security/injection/Marshal.qll @@ -1,26 +1,23 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious marshals. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization +private FunctionObject marshalLoads() { result = ModuleObject::named("marshal").attr("loads") } -private FunctionObject marshalLoads() { - result = ModuleObject::named("marshal").attr("loads") -} - - -/** A taint sink that is potentially vulnerable to malicious marshaled objects. - * The `vuln` in `marshal.loads(vuln)`. */ +/** + * A taint sink that is potentially vulnerable to malicious marshaled objects. + * The `vuln` in `marshal.loads(vuln)`. + */ class UnmarshalingNode extends DeserializationSink { - override string toString() { result = "unmarshaling vulnerability" } UnmarshalingNode() { @@ -30,8 +27,5 @@ class UnmarshalingNode extends DeserializationSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/injection/Path.qll b/python/ql/src/semmle/python/security/injection/Path.qll index 31676430a45..833bd9f1960 100644 --- a/python/ql/src/semmle/python/security/injection/Path.qll +++ b/python/ql/src/semmle/python/security/injection/Path.qll @@ -1,28 +1,22 @@ import python - import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted -/** Prevents taint flowing through ntpath.normpath() +/** + * Prevents taint flowing through ntpath.normpath() * NormalizedPath below handles that case. */ class PathSanitizer extends Sanitizer { - - PathSanitizer() { - this = "path.sanitizer" - } + PathSanitizer() { this = "path.sanitizer" } override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) { taint instanceof ExternalStringKind and abspath_call(node, _) } - } private FunctionObject abspath() { - exists(ModuleObject os_path | - ModuleObject::named("os").attr("path") = os_path - | + exists(ModuleObject os_path | ModuleObject::named("os").attr("path") = os_path | os_path.attr("abspath") = result or os_path.attr("normpath") = result @@ -31,15 +25,9 @@ private FunctionObject abspath() { /** A path that has been normalized, but not verified to be safe */ class NormalizedPath extends TaintKind { + NormalizedPath() { this = "normalized.path.injection" } - NormalizedPath() { - this = "normalized.path.injection" - } - - override string repr() { - result = "normalized path" - } - + override string repr() { result = "normalized path" } } private predicate abspath_call(CallNode call, ControlFlowNode arg) { @@ -47,39 +35,31 @@ private predicate abspath_call(CallNode call, ControlFlowNode arg) { arg = call.getArg(0) } - class AbsPath extends DataFlowExtension::DataFlowNode { + AbsPath() { abspath_call(_, this) } - AbsPath() { - abspath_call(_, this) + override ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) { + abspath_call(result, this) and + tokind instanceof NormalizedPath and + fromkind instanceof ExternalStringKind } - - override - ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) { - abspath_call(result, this) and tokind instanceof NormalizedPath and fromkind instanceof ExternalStringKind - } - } class NormalizedPathSanitizer extends Sanitizer { - - NormalizedPathSanitizer() { - this = "normalized.path.sanitizer" - } + NormalizedPathSanitizer() { this = "normalized.path.sanitizer" } override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { taint instanceof NormalizedPath and test.getTest().(CallNode).getFunction().(AttrNode).getName() = "startswith" and test.getSense() = true } - } -/** A taint sink that is vulnerable to malicious paths. +/** + * A taint sink that is vulnerable to malicious paths. * The `vuln` in `open(vuln)` and similar. */ class OpenNode extends TaintSink { - override string toString() { result = "argument to open()" } OpenNode() { @@ -94,10 +74,4 @@ class OpenNode extends TaintSink { or kind instanceof NormalizedPath } - } - - - - - diff --git a/python/ql/src/semmle/python/security/injection/Pickle.qll b/python/ql/src/semmle/python/security/injection/Pickle.qll index 7faefbdd685..2d56bc25f8e 100644 --- a/python/ql/src/semmle/python/security/injection/Pickle.qll +++ b/python/ql/src/semmle/python/security/injection/Pickle.qll @@ -1,17 +1,16 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious pickles. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization - private ModuleObject pickleModule() { result.getName() = "pickle" or @@ -20,13 +19,10 @@ private ModuleObject pickleModule() { result.getName() = "dill" } -private FunctionObject pickleLoads() { - result = pickleModule().attr("loads") -} +private FunctionObject pickleLoads() { result = pickleModule().attr("loads") } /** `pickle.loads(untrusted)` vulnerability. */ class UnpicklingNode extends DeserializationSink { - override string toString() { result = "unpickling untrusted data" } UnpicklingNode() { @@ -36,8 +32,5 @@ class UnpicklingNode extends DeserializationSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/injection/Sql.qll b/python/ql/src/semmle/python/security/injection/Sql.qll index 07ee883ccf5..38c0eaec7d7 100644 --- a/python/ql/src/semmle/python/security/injection/Sql.qll +++ b/python/ql/src/semmle/python/security/injection/Sql.qll @@ -1,29 +1,27 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious SQL queries or parts of queries. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.SQL - private StringObject first_part(ControlFlowNode command) { command.(BinaryExprNode).getOp() instanceof Add and command.(BinaryExprNode).getLeft().refersTo(result) or - exists(CallNode call, SequenceObject seq | - call = command | + exists(CallNode call, SequenceObject seq | call = command | call = theStrType().lookupAttribute("join") and call.getArg(0).refersTo(seq) and seq.getInferredElement(0) = result ) or - command.(BinaryExprNode).getOp() instanceof Mod and + command.(BinaryExprNode).getOp() instanceof Mod and command.getNode().(StrConst).getLiteralObject() = result } @@ -32,52 +30,45 @@ predicate probable_sql_command(ControlFlowNode command, ControlFlowNode inject) exists(string prefix | inject = command.getAChild*() and first_part(command).getText().regexpMatch(" *" + prefix + ".*") - | + | prefix = "CREATE" or prefix = "SELECT" ) } -/** A taint kind representing a DB cursor. +/** + * A taint kind representing a DB cursor. * This will be overridden to provide specific kinds of DB cursor. */ abstract class DbCursor extends TaintKind { - bindingset[this] DbCursor() { any() } string getExecuteMethodName() { result = "execute" } - } -/** A part of a string that appears to be a SQL command and is thus +/** + * A part of a string that appears to be a SQL command and is thus * vulnerable to malicious input. */ class SimpleSqlStringInjection extends SqlInjectionSink { - override string toString() { result = "simple SQL string injection" } - SimpleSqlStringInjection() { - probable_sql_command(_, this) - } - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } + SimpleSqlStringInjection() { probable_sql_command(_, this) } + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } -/** A taint source representing sources of DB connections. +/** + * A taint source representing sources of DB connections. * This will be overridden to provide specific kinds of DB connection sources. */ -abstract class DbConnectionSource extends TaintSource { +abstract class DbConnectionSource extends TaintSource { } -} - -/** A taint sink that is vulnerable to malicious SQL queries. +/** + * A taint sink that is vulnerable to malicious SQL queries. * The `vuln` in `db.connection.execute(vuln)` and similar. */ class DbConnectionExecuteArgument extends SqlInjectionSink { - override string toString() { result = "db.connection.execute" } DbConnectionExecuteArgument() { @@ -88,9 +79,5 @@ class DbConnectionExecuteArgument extends SqlInjectionSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } - - diff --git a/python/ql/src/semmle/python/security/injection/Xml.qll b/python/ql/src/semmle/python/security/injection/Xml.qll index 7ab628b0085..080df3067d0 100644 --- a/python/ql/src/semmle/python/security/injection/Xml.qll +++ b/python/ql/src/semmle/python/security/injection/Xml.qll @@ -1,36 +1,26 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious XML objects. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization +private ModuleObject xmlElementTreeModule() { result.getName() = "xml.etree.ElementTree" } -private ModuleObject xmlElementTreeModule() { - result.getName() = "xml.etree.ElementTree" -} +private ModuleObject xmlMiniDomModule() { result.getName() = "xml.dom.minidom" } -private ModuleObject xmlMiniDomModule() { - result.getName() = "xml.dom.minidom" -} +private ModuleObject xmlPullDomModule() { result.getName() = "xml.dom.pulldom" } -private ModuleObject xmlPullDomModule() { - result.getName() = "xml.dom.pulldom" -} - -private ModuleObject xmlSaxModule() { - result.getName() = "xml.sax" -} +private ModuleObject xmlSaxModule() { result.getName() = "xml.sax" } private class ExpatParser extends TaintKind { - ExpatParser() { this = "expat.parser" } - } private FunctionObject expatCreateParseFunction() { @@ -38,18 +28,11 @@ private FunctionObject expatCreateParseFunction() { } private class ExpatCreateParser extends TaintSource { + ExpatCreateParser() { expatCreateParseFunction().getACall() = this } - ExpatCreateParser() { - expatCreateParseFunction().getACall() = this - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExpatParser } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExpatParser - } - - string toString() { - result = "expat.create.parser" - } + string toString() { result = "expat.create.parser" } } private FunctionObject xmlFromString() { @@ -64,30 +47,22 @@ private FunctionObject xmlFromString() { /** A (potentially) malicious XML string. */ class ExternalXmlString extends ExternalStringKind { - - ExternalXmlString() { - this = "external xml encoded object" - } - + ExternalXmlString() { this = "external xml encoded object" } } -/** A call to an XML library function that is potentially vulnerable to a +/** + * A call to an XML library function that is potentially vulnerable to a * specially crafted XML string. */ class XmlLoadNode extends DeserializationSink { - override string toString() { result = "xml.load vulnerability" } XmlLoadNode() { - exists(CallNode call | - call.getAnArg() = this | + exists(CallNode call | call.getAnArg() = this | xmlFromString().getACall() = call or any(ExpatParser parser).taints(call.getFunction().(AttrNode).getObject("Parse")) ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalXmlString - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlString } } diff --git a/python/ql/src/semmle/python/security/injection/Yaml.qll b/python/ql/src/semmle/python/security/injection/Yaml.qll index d0c6b1b6723..3b0156b2812 100644 --- a/python/ql/src/semmle/python/security/injection/Yaml.qll +++ b/python/ql/src/semmle/python/security/injection/Yaml.qll @@ -1,25 +1,20 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious yaml-encoded objects. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ import python - import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization - -private FunctionObject yamlLoad() { - result = ModuleObject::named("yaml").attr("load") -} +private FunctionObject yamlLoad() { result = ModuleObject::named("yaml").attr("load") } /** `yaml.load(untrusted)` vulnerability. */ class YamlLoadNode extends DeserializationSink { - override string toString() { result = "yaml.load vulnerability" } YamlLoadNode() { @@ -29,8 +24,5 @@ class YamlLoadNode extends DeserializationSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/strings/Basic.qll b/python/ql/src/semmle/python/security/strings/Basic.qll index bb3c871cd55..56756bb4846 100755 --- a/python/ql/src/semmle/python/security/strings/Basic.qll +++ b/python/ql/src/semmle/python/security/strings/Basic.qll @@ -1,15 +1,11 @@ import python private import Common - import semmle.python.security.TaintTracking /** An extensible kind of taint representing any kind of string. */ abstract class StringKind extends TaintKind { - bindingset[this] - StringKind() { - this = this - } + StringKind() { this = this } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { result = this and @@ -27,43 +23,44 @@ abstract class StringKind extends TaintKind { } override ClassValue getType() { - result = Value::named("bytes") or result = Value::named("str") or result = Value::named("unicode") + result = Value::named("bytes") or + result = Value::named("str") or + result = Value::named("unicode") } - } private class StringEqualitySanitizer extends Sanitizer { - StringEqualitySanitizer() { this = "string equality sanitizer" } /** The test `if untrusted == "KNOWN_VALUE":` sanitizes `untrusted` on its `true` edge. */ override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { taint instanceof StringKind and - exists(ControlFlowNode const, Cmpop op | - const.getNode() instanceof StrConst | + exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst | ( test.getTest().(CompareNode).operands(const, op, _) or test.getTest().(CompareNode).operands(_, op, const) - ) and ( + ) and + ( op instanceof Eq and test.getSense() = true or op instanceof NotEq and test.getSense() = false ) ) } - } /* tonode = fromnode.xxx() where the call to xxx returns an identical or similar string */ private predicate str_method_call(ControlFlowNode fromnode, CallNode tonode) { - exists(string method_name | - tonode.getFunction().(AttrNode).getObject(method_name) = fromnode - | - method_name = "strip" or method_name = "format" or - method_name = "lstrip" or method_name = "rstrip" or - method_name = "ljust" or method_name = "rjust" or - method_name = "title" or method_name = "capitalize" + exists(string method_name | tonode.getFunction().(AttrNode).getObject(method_name) = fromnode | + method_name = "strip" or + method_name = "format" or + method_name = "lstrip" or + method_name = "rstrip" or + method_name = "ljust" or + method_name = "rjust" or + method_name = "title" or + method_name = "capitalize" ) } @@ -79,8 +76,10 @@ private predicate encode_decode(ControlFlowNode fromnode, CallNode tonode) { not func.getFunction().isMethod() and func.getACall() = tonode and tonode.getAnArg() = fromnode and - func.getName() = name | - name = "encode" or name = "decode" or + func.getName() = name + | + name = "encode" or + name = "decode" or name = "decodestring" ) } @@ -99,22 +98,19 @@ private predicate to_str(ControlFlowNode fromnode, CallNode tonode) { private predicate slice(ControlFlowNode fromnode, SubscriptNode tonode) { exists(Slice all | all = tonode.getIndex().getNode() and - not exists(all.getStart()) and not exists(all.getStop()) and + not exists(all.getStart()) and + not exists(all.getStop()) and tonode.getObject() = fromnode ) } /* tonode = os.path.join(..., fromnode, ...) */ private predicate os_path_join(ControlFlowNode fromnode, CallNode tonode) { - tonode = Value::named("os.path.join").getACall() - and tonode.getAnArg() = fromnode + tonode = Value::named("os.path.join").getACall() and + tonode.getAnArg() = fromnode } /** A kind of "taint", representing a dictionary mapping str->"taint" */ class StringDictKind extends DictKind { - - StringDictKind() { - this.getValue() instanceof StringKind - } - + StringDictKind() { this.getValue() instanceof StringKind } } diff --git a/python/ql/src/semmle/python/security/strings/Common.qll b/python/ql/src/semmle/python/security/strings/Common.qll index 6ac796d109b..404da271d78 100644 --- a/python/ql/src/semmle/python/security/strings/Common.qll +++ b/python/ql/src/semmle/python/security/strings/Common.qll @@ -1,12 +1,10 @@ import python - /* A call that returns a copy (or similar) of the argument */ predicate copy_call(ControlFlowNode fromnode, CallNode tonode) { tonode.getFunction().(AttrNode).getObject("copy") = fromnode or - exists(ModuleValue copy, string name | - name = "copy" or name = "deepcopy" | + exists(ModuleValue copy, string name | name = "copy" or name = "deepcopy" | copy.attr(name).(FunctionValue).getACall() = tonode and tonode.getArg(0) = fromnode ) diff --git a/python/ql/src/semmle/python/security/strings/External.qll b/python/ql/src/semmle/python/security/strings/External.qll index c8084552a5d..6a7261c4be3 100644 --- a/python/ql/src/semmle/python/security/strings/External.qll +++ b/python/ql/src/semmle/python/security/strings/External.qll @@ -206,7 +206,6 @@ class ExternalFileObject extends TaintKind { */ class UrlsplitUrlparseTempSanitizer extends Sanitizer { // TODO: remove this once we have better support for named tuples - UrlsplitUrlparseTempSanitizer() { this = "UrlsplitUrlparseTempSanitizer" } override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { @@ -238,9 +237,7 @@ class UrlsplitUrlparseTempSanitizer extends Sanitizer { /** holds for `== "KNOWN_VALUE"` on `true` edge, and `!= "KNOWN_VALUE"` on `false` edge */ private predicate test_equality_with_const(CompareNode cmp, ControlFlowNode tainted, boolean sense) { - exists(ControlFlowNode const, Cmpop op | - const.getNode() instanceof StrConst - | + exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst | ( cmp.operands(const, op, tainted) or @@ -257,7 +254,9 @@ class UrlsplitUrlparseTempSanitizer extends Sanitizer { /** holds for `in ["KNOWN_VALUE", ...]` on `true` edge, and `not in ["KNOWN_VALUE", ...]` on `false` edge */ private predicate test_in_const_seq(CompareNode cmp, ControlFlowNode tainted, boolean sense) { exists(SequenceNode const_seq, Cmpop op | - forall(ControlFlowNode elem | elem = const_seq.getAnElement() | elem.getNode() instanceof StrConst) + forall(ControlFlowNode elem | elem = const_seq.getAnElement() | + elem.getNode() instanceof StrConst + ) | cmp.operands(tainted, op, const_seq) and ( diff --git a/python/ql/src/semmle/python/security/strings/Untrusted.qll b/python/ql/src/semmle/python/security/strings/Untrusted.qll index 65e624aa1b7..6fa12668ada 100644 --- a/python/ql/src/semmle/python/security/strings/Untrusted.qll +++ b/python/ql/src/semmle/python/security/strings/Untrusted.qll @@ -1,14 +1,10 @@ import python import External - -/** A kind of taint representing an externally controlled string. +/** + * A kind of taint representing an externally controlled string. * This class is a simple sub-class of `ExternalStringKind`. */ class UntrustedStringKind extends ExternalStringKind { - - UntrustedStringKind() { - this = "externally controlled string" - } - + UntrustedStringKind() { this = "externally controlled string" } } From 5b121b772391872ce5acbfbd8fa74852984607ae Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:37:06 +0100 Subject: [PATCH 112/459] Python: Autoformat `values`. --- .../ql/src/semmle/python/types/Builtins.qll | 74 ++-- .../src/semmle/python/types/ClassObject.qll | 406 +++++++----------- .../src/semmle/python/types/Descriptors.qll | 22 +- .../ql/src/semmle/python/types/Exceptions.qll | 232 +++++----- .../ql/src/semmle/python/types/Extensions.qll | 89 ++-- .../semmle/python/types/FunctionObject.qll | 241 ++++------- .../ql/src/semmle/python/types/ImportTime.qll | 17 +- .../ql/src/semmle/python/types/ModuleKind.qll | 11 +- .../src/semmle/python/types/ModuleObject.qll | 191 +++----- python/ql/src/semmle/python/types/Object.qll | 313 +++++--------- .../ql/src/semmle/python/types/Properties.qll | 100 ++--- python/ql/src/semmle/python/types/Version.qll | 14 +- 12 files changed, 642 insertions(+), 1068 deletions(-) diff --git a/python/ql/src/semmle/python/types/Builtins.qll b/python/ql/src/semmle/python/types/Builtins.qll index e87e88c1c4b..a369218843e 100644 --- a/python/ql/src/semmle/python/types/Builtins.qll +++ b/python/ql/src/semmle/python/types/Builtins.qll @@ -1,14 +1,15 @@ import python class Builtin extends @py_cobject { - Builtin() { not ( /* @py_cobjects for modules which have a corresponding Python module */ - exists(@py_cobject mod_type | py_special_objects(mod_type, "ModuleType") and py_cobjecttypes(this, mod_type)) and + exists(@py_cobject mod_type | + py_special_objects(mod_type, "ModuleType") and py_cobjecttypes(this, mod_type) + ) and exists(Module m | py_cobjectnames(this, m.getName())) - ) - and ( + ) and + ( /* Exclude unmatched builtin objects in the library trap files */ py_cobjectnames(this, _) or py_cobjecttypes(this, _) or @@ -17,9 +18,11 @@ class Builtin extends @py_cobject { } string toString() { - not this = undefinedVariable().asBuiltin() and not this = Builtin::unknown() and + not this = undefinedVariable().asBuiltin() and + not this = Builtin::unknown() and exists(Builtin type, string typename, string objname | - py_cobjecttypes(this, type) and py_cobjectnames(this, objname) and typename = type.getName() | + py_cobjecttypes(this, type) and py_cobjectnames(this, objname) and typename = type.getName() + | result = typename + " " + objname ) } @@ -35,9 +38,7 @@ class Builtin extends @py_cobject { py_cmembers_versioned(this, name, result, major_version().toString()) } - Builtin getItem(int index) { - py_citems(this, index, result) - } + Builtin getItem(int index) { py_citems(this, index, result) } Builtin getBaseClass() { /* The extractor uses the special name ".super." to indicate the super class of a builtin class */ @@ -50,12 +51,7 @@ class Builtin extends @py_cobject { this.getBaseClass().inheritsFromType() } - string getName() { - if this.isStr() then - result = "str" - else - py_cobjectnames(this, result) - } + string getName() { if this.isStr() then result = "str" else py_cobjectnames(this, result) } private predicate isStr() { major_version() = 2 and this = Builtin::special("bytes") @@ -64,8 +60,10 @@ class Builtin extends @py_cobject { } predicate isClass() { - py_cobjecttypes(_, this) or - this = Builtin::unknownType() or + py_cobjecttypes(_, this) + or + this = Builtin::unknownType() + or exists(Builtin meta | meta.inheritsFromType() and py_cobjecttypes(this, meta)) } @@ -77,9 +75,7 @@ class Builtin extends @py_cobject { ) } - predicate isModule() { - this.getClass() = Builtin::special("ModuleType") - } + predicate isModule() { this.getClass() = Builtin::special("ModuleType") } predicate isMethod() { this.getClass() = Builtin::special("MethodDescriptorType") @@ -88,50 +84,42 @@ class Builtin extends @py_cobject { } int intValue() { - (this.getClass() = Builtin::special("int") or - this.getClass() = Builtin::special("long")) and + ( + this.getClass() = Builtin::special("int") or + this.getClass() = Builtin::special("long") + ) and result = this.getName().toInt() } float floatValue() { - (this.getClass() = Builtin::special("float")) and + this.getClass() = Builtin::special("float") and result = this.getName().toFloat() } string strValue() { - (this.getClass() = Builtin::special("unicode") or - this.getClass() = Builtin::special("bytes")) and + ( + this.getClass() = Builtin::special("unicode") or + this.getClass() = Builtin::special("bytes") + ) and exists(string quoted_string | - quoted_string = this.getName() - and + quoted_string = this.getName() and result = quoted_string.regexpCapture("[bu]'([\\s\\S]*)'", 1) ) } - } module Builtin { - Builtin builtinModule() { py_special_objects(result, "builtin_module_2") and major_version() = 2 or py_special_objects(result, "builtin_module_3") and major_version() = 3 } - Builtin builtin(string name) { - result = builtinModule().getMember(name) - } + Builtin builtin(string name) { result = builtinModule().getMember(name) } - Builtin special(string name) { - py_special_objects(result, name) - } + Builtin special(string name) { py_special_objects(result, name) } - Builtin unknown() { - py_special_objects(result, "_1") - } + Builtin unknown() { py_special_objects(result, "_1") } - Builtin unknownType() { - py_special_objects(result, "_semmle_unknown_type") - } - -} \ No newline at end of file + Builtin unknownType() { py_special_objects(result, "_semmle_unknown_type") } +} diff --git a/python/ql/src/semmle/python/types/ClassObject.qll b/python/ql/src/semmle/python/types/ClassObject.qll index fc2b64bc32a..d48a9bddf22 100644 --- a/python/ql/src/semmle/python/types/ClassObject.qll +++ b/python/ql/src/semmle/python/types/ClassObject.qll @@ -6,22 +6,21 @@ private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins private import semmle.python.objects.ObjectInternal - -/** A class whose instances represents Python classes. - * Instances of this class represent either builtin classes - * such as `list` or `str`, or program-defined Python classes +/** + * A class whose instances represents Python classes. + * Instances of this class represent either builtin classes + * such as `list` or `str`, or program-defined Python classes * present in the source code. - * - * Generally there is a one-to-one mapping between classes in - * the Python program and instances of this class in the database. - * However, that is not always the case. For example, dynamically + * + * Generally there is a one-to-one mapping between classes in + * the Python program and instances of this class in the database. + * However, that is not always the case. For example, dynamically * generated classes may share a single QL class instance. - * Also the existence of a class definition in the source code - * does not guarantee that such a class will ever exist in the + * Also the existence of a class definition in the source code + * does not guarantee that such a class will ever exist in the * running program. */ class ClassObject extends Object { - private ClassObjectInternal theClass() { result.getOrigin() = this or @@ -34,11 +33,10 @@ class ClassObject extends Object { } /** Gets the short (unqualified) name of this class */ - string getName() { - result = theClass().getName() - } + string getName() { result = theClass().getName() } - /** Gets the qualified name for this class. + /** + * Gets the qualified name for this class. * Should return the same name as the `__qualname__` attribute on classes in Python 3. */ string getQualifiedName() { @@ -48,19 +46,13 @@ class ClassObject extends Object { } /** Gets the nth base class of this class */ - Object getBaseType(int n) { - result = Types::getBase(theClass(), n).getSource() - } + Object getBaseType(int n) { result = Types::getBase(theClass(), n).getSource() } /** Gets a base class of this class */ - Object getABaseType() { - result = this.getBaseType(_) - } + Object getABaseType() { result = this.getBaseType(_) } /** Whether this class has a base class */ - predicate hasABase() { - exists(Types::getBase(theClass(), _)) - } + predicate hasABase() { exists(Types::getBase(theClass(), _)) } /** Gets a super class of this class (includes transitive super classes) */ ClassObject getASuperType() { @@ -68,35 +60,34 @@ class ClassObject extends Object { } /** Gets a super class of this class (includes transitive super classes) or this class */ - ClassObject getAnImproperSuperType() { - result = this.getABaseType*() - } + ClassObject getAnImproperSuperType() { result = this.getABaseType*() } - /** Whether this class is a new style class. - * A new style class is one that implicitly or explicitly inherits from `object`. */ - predicate isNewStyle() { - Types::isNewStyle(theClass()) - } + /** + * Whether this class is a new style class. + * A new style class is one that implicitly or explicitly inherits from `object`. + */ + predicate isNewStyle() { Types::isNewStyle(theClass()) } - /** Whether this class is an old style class. - * An old style class is one that does not inherit from `object`. */ - predicate isOldStyle() { - Types::isOldStyle(theClass()) - } + /** + * Whether this class is an old style class. + * An old style class is one that does not inherit from `object`. + */ + predicate isOldStyle() { Types::isOldStyle(theClass()) } - /** Whether this class is a legal exception class. - * What constitutes a legal exception class differs between major versions */ + /** + * Whether this class is a legal exception class. + * What constitutes a legal exception class differs between major versions + */ predicate isLegalExceptionType() { - not this.isNewStyle() or + not this.isNewStyle() + or this.getAnImproperSuperType() = theBaseExceptionType() or major_version() = 2 and this = theTupleType() } /** Gets the scope associated with this class, if it is not a builtin class */ - Class getPyClass() { - result.getClassObject() = this - } + Class getPyClass() { result.getClassObject() = this } /** Returns an attribute declared on this class (not on a super-class) */ Object declaredAttribute(string name) { @@ -111,8 +102,10 @@ class ClassObject extends Object { theClass().getClassDeclaration().declaresAttribute(name) } - /** Returns an attribute as it would be when looked up at runtime on this class. - * Will include attributes of super-classes */ + /** + * Returns an attribute as it would be when looked up at runtime on this class. + * Will include attributes of super-classes + */ Object lookupAttribute(string name) { exists(ObjectInternal val | theClass().lookup(name, val, _) and @@ -120,9 +113,7 @@ class ClassObject extends Object { ) } - ClassList getMro() { - result = Types::getMro(theClass()) - } + ClassList getMro() { result = Types::getMro(theClass()) } /** Looks up an attribute by searching this class' MRO starting at `start` */ Object lookupMro(ClassObject start, string name) { @@ -149,21 +140,20 @@ class ClassObject extends Object { ) } - /** Whether this class has a attribute named `name`, either declared or inherited.*/ - predicate hasAttribute(string name) { - theClass().hasAttribute(name) - } + /** Whether this class has a attribute named `name`, either declared or inherited. */ + predicate hasAttribute(string name) { theClass().hasAttribute(name) } - /** Whether it is impossible to know all the attributes of this class. Usually because it is - * impossible to calculate the full class hierarchy or because some attribute is too dynamic. */ + /** + * Whether it is impossible to know all the attributes of this class. Usually because it is + * impossible to calculate the full class hierarchy or because some attribute is too dynamic. + */ predicate unknowableAttributes() { /* True for a class with undeterminable superclasses, unanalysable metaclasses, or other confusions */ this.failedInference() or this.getMetaClass().failedInference() or - exists(Object base | - base = this.getABaseType() | + exists(Object base | base = this.getABaseType() | base.(ClassObject).unknowableAttributes() or not base instanceof ClassObject @@ -172,8 +162,7 @@ class ClassObject extends Object { /** Gets the metaclass for this class */ ClassObject getMetaClass() { - result = theClass().getClass().getSource() - and + result = theClass().getClass().getSource() and not this.failedInference() } @@ -183,35 +172,29 @@ class ClassObject extends Object { or exists(FunctionObject f, Raise r, Name ex | f = this.lookupAttribute(_) and - r.getScope() = f.getFunction() | + r.getScope() = f.getFunction() + | (r.getException() = ex or r.getException().(Call).getFunc() = ex) and (ex.getId() = "NotImplementedError" or ex.getId() = "NotImplemented") ) } - ControlFlowNode declaredMetaClass() { - result = this.getPyClass().getMetaClass().getAFlowNode() - } + ControlFlowNode declaredMetaClass() { result = this.getPyClass().getMetaClass().getAFlowNode() } - /** Has type inference failed to compute the full class hierarchy for this class for the reason given. */ - predicate failedInference(string reason) { - Types::failedInference(theClass(), reason) - } + /** Has type inference failed to compute the full class hierarchy for this class for the reason given. */ + predicate failedInference(string reason) { Types::failedInference(theClass(), reason) } - /** Has type inference failed to compute the full class hierarchy for this class */ - predicate failedInference() { - this.failedInference(_) - } + /** Has type inference failed to compute the full class hierarchy for this class */ + predicate failedInference() { this.failedInference(_) } - /** Gets an object which is the sole instance of this class, if this class is probably a singleton. + /** + * Gets an object which is the sole instance of this class, if this class is probably a singleton. * Note the 'probable' in the name; there is no guarantee that this class is in fact a singleton. - * It is guaranteed that getProbableSingletonInstance() returns at most one Object for each ClassObject. */ + * It is guaranteed that getProbableSingletonInstance() returns at most one Object for each ClassObject. + */ Object getProbableSingletonInstance() { - exists(ControlFlowNode use, Expr origin | - use.refersTo(result, this, origin.getAFlowNode()) - | - this.hasStaticallyUniqueInstance() - and + exists(ControlFlowNode use, Expr origin | use.refersTo(result, this, origin.getAFlowNode()) | + this.hasStaticallyUniqueInstance() and /* Ensure that original expression will be executed only one. */ origin.getScope() instanceof ImportTimeScope and not exists(Expr outer | outer.getASubExpression+() = origin) @@ -225,9 +208,7 @@ class ClassObject extends Object { strictcount(SpecificInstanceInternal inst | inst.getClass() = theClass()) = 1 } - ImportTimeScope getImportTimeScope() { - result = this.getPyClass() - } + ImportTimeScope getImportTimeScope() { result = this.getPyClass() } override string toString() { this.isC() and result = "builtin-class " + this.getName() and not this = theUnknownType() @@ -236,84 +217,81 @@ class ClassObject extends Object { } /* Method Resolution Order */ - /** Returns the next class in the MRO of 'this' after 'sup' */ - ClassObject nextInMro(ClassObject sup) { - exists(ClassObjectInternal other | + ClassObject nextInMro(ClassObject sup) { + exists(ClassObjectInternal other | other.getSource() = sup and result = Types::getMro(theClass()).startingAt(other).getTail().getHead().getSource() ) and not this.failedInference() } - /** Gets the MRO for this class. ClassObject `sup` occurs at `index` in the list of classes. + /** + * Gets the MRO for this class. ClassObject `sup` occurs at `index` in the list of classes. * `this` has an index of `1`, the next class in the MRO has an index of `2`, and so on. */ - ClassObject getMroItem(int index) { - result = this.getMro().getItem(index).getSource() - } + ClassObject getMroItem(int index) { result = this.getMro().getItem(index).getSource() } /** Holds if this class has duplicate base classes */ predicate hasDuplicateBases() { - exists(ClassObject base, int i, int j | i != j and base = this.getBaseType(i) and base = this.getBaseType(j)) + exists(ClassObject base, int i, int j | + i != j and base = this.getBaseType(i) and base = this.getBaseType(j) + ) } /** Holds if this class is an iterable. */ - predicate isIterable() { - this.hasAttribute("__iter__") or this.hasAttribute("__getitem__") - } + predicate isIterable() { this.hasAttribute("__iter__") or this.hasAttribute("__getitem__") } /** Holds if this class is an iterator. */ predicate isIterator() { - this.hasAttribute("__iter__") and - (major_version() = 3 and this.hasAttribute("__next__") - or - /* Because 'next' is a common method name we need to check that an __iter__ - * method actually returns this class. This is not needed for Py3 as the - * '__next__' method exists to define a class as an iterator. - */ - major_version() = 2 and this.hasAttribute("next") and - exists(ClassObject other, FunctionObject iter | - other.declaredAttribute("__iter__") = iter | - iter.getAnInferredReturnType() = this - ) + this.hasAttribute("__iter__") and + ( + major_version() = 3 and this.hasAttribute("__next__") + or + /* + * Because 'next' is a common method name we need to check that an __iter__ + * method actually returns this class. This is not needed for Py3 as the + * '__next__' method exists to define a class as an iterator. + */ + + major_version() = 2 and + this.hasAttribute("next") and + exists(ClassObject other, FunctionObject iter | other.declaredAttribute("__iter__") = iter | + iter.getAnInferredReturnType() = this + ) ) or /* This will be redundant when we have C class information */ this = theGeneratorType() } - /** Holds if this class is an improper subclass of the other class. + /** + * Holds if this class is an improper subclass of the other class. * True if this is a sub-class of other or this is the same class as other. * * Equivalent to the Python builtin function issubclass(). */ - predicate isSubclassOf(ClassObject other) { - this = other or this.getASuperType() = other - } + predicate isSubclassOf(ClassObject other) { this = other or this.getASuperType() = other } /** Synonymous with isContainer(), retained for backwards compatibility. */ - predicate isCollection() { - this.isContainer() - } + predicate isCollection() { this.isContainer() } - /** Holds if this class is a container(). That is, does it have a __getitem__ method.*/ - predicate isContainer() { - exists(this.lookupAttribute("__getitem__")) - } + /** Holds if this class is a container(). That is, does it have a __getitem__ method. */ + predicate isContainer() { exists(this.lookupAttribute("__getitem__")) } /** Holds if this class is a mapping. */ predicate isMapping() { - exists(this.lookupAttribute("__getitem__")) - and + exists(this.lookupAttribute("__getitem__")) and not this.isSequence() } /** Holds if this class is probably a sequence. */ predicate isSequence() { - /* To determine whether something is a sequence or a mapping is not entirely clear, - * so we need to guess a bit. + /* + * To determine whether something is a sequence or a mapping is not entirely clear, + * so we need to guess a bit. */ + this.getAnImproperSuperType() = theTupleType() or this.getAnImproperSuperType() = theListType() @@ -330,18 +308,14 @@ class ClassObject extends Object { /* Does it have an index or __reversed__ method? */ this.isContainer() and ( - this.hasAttribute("index") or + this.hasAttribute("index") or this.hasAttribute("__reversed__") ) } - predicate isCallable() { - this.hasAttribute("__call__") - } + predicate isCallable() { this.hasAttribute("__call__") } - predicate isContextManager() { - this.hasAttribute("__enter__") and this.hasAttribute("__exit__") - } + predicate isContextManager() { this.hasAttribute("__enter__") and this.hasAttribute("__exit__") } predicate assignedInInit(string name) { exists(FunctionObject init | init = this.lookupAttribute("__init__") | @@ -353,17 +327,15 @@ class ClassObject extends Object { predicate unhashable() { this.lookupAttribute("__hash__") = theNoneObject() or - ((FunctionObject)this.lookupAttribute("__hash__")).neverReturns() + this.lookupAttribute("__hash__").(FunctionObject).neverReturns() } /** Holds if this class is a descriptor */ - predicate isDescriptorType() { - this.hasAttribute("__get__") - } + predicate isDescriptorType() { this.hasAttribute("__get__") } /** Holds if this class is an overriding descriptor */ predicate isOverridingDescriptorType() { - this.hasAttribute("__get__") and this.hasAttribute("__set__") + this.hasAttribute("__get__") and this.hasAttribute("__set__") } FunctionObject getAMethodCalledFromInit() { @@ -373,124 +345,80 @@ class ClassObject extends Object { ) } - override boolean booleanValue() { - result = true - } + override boolean booleanValue() { result = true } - /** Gets a call to this class. Note that the call may not create a new instance of + /** + * Gets a call to this class. Note that the call may not create a new instance of * this class, as that depends on the `__new__` method of this class. */ - CallNode getACall() { - result.getFunction().refersTo(this) - } - - override predicate notClass() { - none() - } + CallNode getACall() { result.getFunction().refersTo(this) } + override predicate notClass() { none() } } -/** The 'str' class. This is the same as the 'bytes' class for - * Python 2 and the 'unicode' class for Python 3 */ +/** + * The 'str' class. This is the same as the 'bytes' class for + * Python 2 and the 'unicode' class for Python 3 + */ ClassObject theStrType() { - if major_version() = 2 then - result = theBytesType() - else - result = theUnicodeType() + if major_version() = 2 then result = theBytesType() else result = theUnicodeType() } -private -Module theAbcModule() { - result.getName() = "abc" -} +private Module theAbcModule() { result.getName() = "abc" } ClassObject theAbcMetaClassObject() { /* Avoid using points-to and thus negative recursion */ - exists(Class abcmeta | - result.getPyClass() = abcmeta | + exists(Class abcmeta | result.getPyClass() = abcmeta | abcmeta.getName() = "ABCMeta" and abcmeta.getScope() = theAbcModule() ) } /* Common builtin classes */ - -/** The built-in class NoneType*/ -ClassObject theNoneType() { - result.asBuiltin() = Builtin::special("NoneType") -} +/** The built-in class NoneType */ +ClassObject theNoneType() { result.asBuiltin() = Builtin::special("NoneType") } /** The built-in class 'bool' */ -ClassObject theBoolType() { - result.asBuiltin() = Builtin::special("bool") -} +ClassObject theBoolType() { result.asBuiltin() = Builtin::special("bool") } /** The builtin class 'type' */ -ClassObject theTypeType() { - result.asBuiltin() = Builtin::special("type") -} +ClassObject theTypeType() { result.asBuiltin() = Builtin::special("type") } /** The builtin object ClassType (for old-style classes) */ -ClassObject theClassType() { - result.asBuiltin() = Builtin::special("ClassType") -} +ClassObject theClassType() { result.asBuiltin() = Builtin::special("ClassType") } /** The builtin object InstanceType (for old-style classes) */ -ClassObject theInstanceType() { - result.asBuiltin() = Builtin::special("InstanceType") -} +ClassObject theInstanceType() { result.asBuiltin() = Builtin::special("InstanceType") } /** The builtin class 'tuple' */ -ClassObject theTupleType() { - result.asBuiltin() = Builtin::special("tuple") -} +ClassObject theTupleType() { result.asBuiltin() = Builtin::special("tuple") } /** The builtin class 'int' */ -ClassObject theIntType() { - result.asBuiltin() = Builtin::special("int") -} +ClassObject theIntType() { result.asBuiltin() = Builtin::special("int") } /** The builtin class 'long' (Python 2 only) */ -ClassObject theLongType() { - result.asBuiltin() = Builtin::special("long") -} +ClassObject theLongType() { result.asBuiltin() = Builtin::special("long") } /** The builtin class 'float' */ -ClassObject theFloatType() { - result.asBuiltin() = Builtin::special("float") -} +ClassObject theFloatType() { result.asBuiltin() = Builtin::special("float") } /** The builtin class 'complex' */ -ClassObject theComplexType() { - result.asBuiltin() = Builtin::special("complex") -} +ClassObject theComplexType() { result.asBuiltin() = Builtin::special("complex") } /** The builtin class 'object' */ -ClassObject theObjectType() { - result.asBuiltin() = Builtin::special("object") -} +ClassObject theObjectType() { result.asBuiltin() = Builtin::special("object") } /** The builtin class 'list' */ -ClassObject theListType() { - result.asBuiltin() = Builtin::special("list") -} +ClassObject theListType() { result.asBuiltin() = Builtin::special("list") } /** The builtin class 'dict' */ - -ClassObject theDictType() { - result.asBuiltin() = Builtin::special("dict") -} +ClassObject theDictType() { result.asBuiltin() = Builtin::special("dict") } /** The builtin class 'Exception' */ - -ClassObject theExceptionType() { - result.asBuiltin() = Builtin::special("Exception") -} +ClassObject theExceptionType() { result.asBuiltin() = Builtin::special("Exception") } /** The builtin class for unicode. unicode in Python2, str in Python3 */ -ClassObject theUnicodeType() { - result.asBuiltin() = Builtin::special("unicode") -} +ClassObject theUnicodeType() { result.asBuiltin() = Builtin::special("unicode") } /** The builtin class '(x)range' */ ClassObject theRangeType() { @@ -500,24 +428,16 @@ ClassObject theRangeType() { } /** The builtin class for bytes. str in Python2, bytes in Python3 */ -ClassObject theBytesType() { - result.asBuiltin() = Builtin::special("bytes") -} +ClassObject theBytesType() { result.asBuiltin() = Builtin::special("bytes") } /** The builtin class 'set' */ -ClassObject theSetType() { - result.asBuiltin() = Builtin::special("set") -} +ClassObject theSetType() { result.asBuiltin() = Builtin::special("set") } /** The builtin class 'property' */ -ClassObject thePropertyType() { - result.asBuiltin() = Builtin::special("property") -} +ClassObject thePropertyType() { result.asBuiltin() = Builtin::special("property") } /** The builtin class 'BaseException' */ -ClassObject theBaseExceptionType() { - result.asBuiltin() = Builtin::special("BaseException") -} +ClassObject theBaseExceptionType() { result.asBuiltin() = Builtin::special("BaseException") } /** The class of builtin-functions */ ClassObject theBuiltinFunctionType() { @@ -525,54 +445,36 @@ ClassObject theBuiltinFunctionType() { } /** The class of Python functions */ -ClassObject thePyFunctionType() { - result.asBuiltin() = Builtin::special("FunctionType") -} +ClassObject thePyFunctionType() { result.asBuiltin() = Builtin::special("FunctionType") } /** The builtin class 'classmethod' */ -ClassObject theClassMethodType() { - result.asBuiltin() = Builtin::special("ClassMethod") -} +ClassObject theClassMethodType() { result.asBuiltin() = Builtin::special("ClassMethod") } /** The builtin class 'staticmethod' */ -ClassObject theStaticMethodType() { - result.asBuiltin() = Builtin::special("StaticMethod") -} +ClassObject theStaticMethodType() { result.asBuiltin() = Builtin::special("StaticMethod") } /** The class of modules */ -ClassObject theModuleType() { - result.asBuiltin() = Builtin::special("ModuleType") -} +ClassObject theModuleType() { result.asBuiltin() = Builtin::special("ModuleType") } /** The class of generators */ -ClassObject theGeneratorType() { - result.asBuiltin() = Builtin::special("generator") -} +ClassObject theGeneratorType() { result.asBuiltin() = Builtin::special("generator") } /** The builtin class 'TypeError' */ -ClassObject theTypeErrorType() { - result.asBuiltin() = Builtin::special("TypeError") -} +ClassObject theTypeErrorType() { result.asBuiltin() = Builtin::special("TypeError") } /** The builtin class 'AttributeError' */ -ClassObject theAttributeErrorType() { - result.asBuiltin() = Builtin::special("AttributeError") -} +ClassObject theAttributeErrorType() { result.asBuiltin() = Builtin::special("AttributeError") } /** The builtin class 'KeyError' */ -ClassObject theKeyErrorType() { - result.asBuiltin() = Builtin::special("KeyError") -} +ClassObject theKeyErrorType() { result.asBuiltin() = Builtin::special("KeyError") } /** The builtin class of bound methods */ -pragma [noinline] -ClassObject theBoundMethodType() { - result.asBuiltin() = Builtin::special("MethodType") -} +pragma[noinline] +ClassObject theBoundMethodType() { result.asBuiltin() = Builtin::special("MethodType") } /** The builtin class of builtin properties */ ClassObject theGetSetDescriptorType() { - result.asBuiltin() = Builtin::special("GetSetDescriptorType") + result.asBuiltin() = Builtin::special("GetSetDescriptorType") } /** The method descriptor class */ @@ -582,27 +484,19 @@ ClassObject theMethodDescriptorType() { /** The class of builtin properties */ ClassObject theBuiltinPropertyType() { - /* This is CPython specific */ + /* This is CPython specific */ result.isC() and result.getName() = "getset_descriptor" } /** The builtin class 'IOError' */ -ClassObject theIOErrorType() { - result = Object::builtin("IOError") -} +ClassObject theIOErrorType() { result = Object::builtin("IOError") } /** The builtin class 'super' */ -ClassObject theSuperType() { - result = Object::builtin("super") -} +ClassObject theSuperType() { result = Object::builtin("super") } /** The builtin class 'StopIteration' */ -ClassObject theStopIterationType() { - result = Object::builtin("StopIteration") -} +ClassObject theStopIterationType() { result = Object::builtin("StopIteration") } /** The builtin class 'NotImplementedError' */ -ClassObject theNotImplementedErrorType() { - result = Object::builtin("NotImplementedError") -} +ClassObject theNotImplementedErrorType() { result = Object::builtin("NotImplementedError") } diff --git a/python/ql/src/semmle/python/types/Descriptors.qll b/python/ql/src/semmle/python/types/Descriptors.qll index 949ff1d4266..f190f9a6434 100644 --- a/python/ql/src/semmle/python/types/Descriptors.qll +++ b/python/ql/src/semmle/python/types/Descriptors.qll @@ -1,13 +1,9 @@ import python private import semmle.python.objects.ObjectInternal - -/** A class method object. Either a decorated function or an explicit call to classmethod(f) */ +/** A class method object. Either a decorated function or an explicit call to classmethod(f) */ class ClassMethodObject extends Object { - - ClassMethodObject() { - any(ClassMethodObjectInternal cm).getOrigin() = this - } + ClassMethodObject() { any(ClassMethodObjectInternal cm).getOrigin() = this } FunctionObject getFunction() { exists(ClassMethodObjectInternal cm | @@ -16,18 +12,12 @@ class ClassMethodObject extends Object { ) } - CallNode getACall() { - result = this.getFunction().getACall() - } - + CallNode getACall() { result = this.getFunction().getACall() } } -/** A static method object. Either a decorated function or an explicit call to staticmethod(f) */ +/** A static method object. Either a decorated function or an explicit call to staticmethod(f) */ class StaticMethodObject extends Object { - - StaticMethodObject() { - any(StaticMethodObjectInternal sm).getOrigin() = this - } + StaticMethodObject() { any(StaticMethodObjectInternal sm).getOrigin() = this } FunctionObject getFunction() { exists(StaticMethodObjectInternal sm | @@ -35,6 +25,4 @@ class StaticMethodObject extends Object { result = sm.getFunction().getSource() ) } - } - diff --git a/python/ql/src/semmle/python/types/Exceptions.qll b/python/ql/src/semmle/python/types/Exceptions.qll index 387fa43100d..c6aa76a1919 100644 --- a/python/ql/src/semmle/python/types/Exceptions.qll +++ b/python/ql/src/semmle/python/types/Exceptions.qll @@ -1,6 +1,6 @@ /** * Analysis of exception raising and handling. - * + * * In order to make this useful we make a number of assumptions. These are: * 1. Typing errors (TypeError, NameError, AttributeError) are assumed to occur only if: * a) Explicitly raised, e.g. raise TypeError() @@ -15,7 +15,6 @@ import python /** Subset of ControlFlowNodes which might raise an exception */ class RaisingNode extends ControlFlowNode { - RaisingNode() { exists(this.getAnExceptionalSuccessor()) or @@ -24,63 +23,58 @@ class RaisingNode extends ControlFlowNode { /** Gets the CFG node for the exception, if and only if this RaisingNode is an explicit raise */ ControlFlowNode getExceptionNode() { - exists(Raise r | - r = this.getNode() and result.getNode() = r.getRaised() and + exists(Raise r | + r = this.getNode() and + result.getNode() = r.getRaised() and result.getBasicBlock().dominates(this.getBasicBlock()) ) } - private predicate quits() { - this.(CallNode).getFunction().refersTo(Object::quitter(_)) - } + private predicate quits() { this.(CallNode).getFunction().refersTo(Object::quitter(_)) } - /** Gets the type of an exception that may be raised - * at this control flow node */ + /** + * Gets the type of an exception that may be raised + * at this control flow node + */ ClassObject getARaisedType() { result = this.localRaisedType() or - exists(FunctionObject func | - this = func.getACall() | - result = func.getARaisedType() - ) + exists(FunctionObject func | this = func.getACall() | result = func.getARaisedType()) or result = systemExitRaise() } pragma[noinline] - private ClassObject systemExitRaise() { - this.quits() and result = Object::builtin("SystemExit") - } + private ClassObject systemExitRaise() { this.quits() and result = Object::builtin("SystemExit") } - pragma [noinline, nomagic] + pragma[noinline, nomagic] private ClassObject localRaisedType() { - result.isSubclassOf(theBaseExceptionType()) - and + result.isSubclassOf(theBaseExceptionType()) and ( - exists(ControlFlowNode ex | - ex = this.getExceptionNode() and - (ex.refersTo(result) or ex.refersTo(_, result, _)) - ) - or - this.getNode() instanceof ImportExpr and result = Object::builtin("ImportError") - or - this.getNode() instanceof Print and result = theIOErrorType() - or - exists(ExceptFlowNode except | - except = this.getAnExceptionalSuccessor() and - except.handles(result) and - result = this.innateException() - ) - or - not exists(ExceptFlowNode except | except = this.getAnExceptionalSuccessor()) - and - sequence_or_mapping(this) and result = theLookupErrorType() - or - this.read_write_call() and result = theIOErrorType() + exists(ControlFlowNode ex | + ex = this.getExceptionNode() and + (ex.refersTo(result) or ex.refersTo(_, result, _)) + ) + or + this.getNode() instanceof ImportExpr and result = Object::builtin("ImportError") + or + this.getNode() instanceof Print and result = theIOErrorType() + or + exists(ExceptFlowNode except | + except = this.getAnExceptionalSuccessor() and + except.handles(result) and + result = this.innateException() + ) + or + not exists(ExceptFlowNode except | except = this.getAnExceptionalSuccessor()) and + sequence_or_mapping(this) and + result = theLookupErrorType() + or + this.read_write_call() and result = theIOErrorType() ) } - pragma [noinline] + pragma[noinline] ClassObject innateException() { this.getNode() instanceof Attribute and result = theAttributeErrorType() or @@ -91,30 +85,29 @@ class RaisingNode extends ControlFlowNode { this.getNode() instanceof Subscript and result = theKeyErrorType() } - /** Whether this control flow node raises an exception, - * but the type of the exception it raises cannot be inferred. */ + /** + * Whether this control flow node raises an exception, + * but the type of the exception it raises cannot be inferred. + */ predicate raisesUnknownType() { /* read/write calls are assumed to raise IOError (OSError for Py3) */ - not this.read_write_call() - and + not this.read_write_call() and ( - /* Call to an unknown object */ - this.getNode() instanceof Call and not exists(FunctionObject func | this = func.getACall()) - and not exists(ClassObject known | this.(CallNode).getFunction().refersTo(known)) - or - this.getNode() instanceof Exec - or - /* Call to a function raising an unknown type */ - exists(FunctionObject func | - this = func.getACall() | - func.raisesUnknownType() - ) + /* Call to an unknown object */ + this.getNode() instanceof Call and + not exists(FunctionObject func | this = func.getACall()) and + not exists(ClassObject known | this.(CallNode).getFunction().refersTo(known)) + or + this.getNode() instanceof Exec + or + /* Call to a function raising an unknown type */ + exists(FunctionObject func | this = func.getACall() | func.raisesUnknownType()) ) } private predicate read_write_call() { exists(string mname | mname = this.(CallNode).getFunction().(AttrNode).getName() | - mname = "read" or mname = "write" + mname = "read" or mname = "write" ) } @@ -143,23 +136,26 @@ class RaisingNode extends ControlFlowNode { raised.isLegalExceptionType() and raised = this.getARaisedType() and succ = this.getAnExceptionalSuccessor() and - ( + ( /* An 'except' that handles raised and there is no more previous handler */ - ((ExceptFlowNode)succ).handles(raised) and - not exists(ExceptFlowNode other, StmtList s, int i, int j | - not other = succ and other.handles(raised) and - s.getItem(i) = succ.getNode() and s.getItem(j) = other.getNode() - | + succ.(ExceptFlowNode).handles(raised) and + not exists(ExceptFlowNode other, StmtList s, int i, int j | + not other = succ and + other.handles(raised) and + s.getItem(i) = succ.getNode() and + s.getItem(j) = other.getNode() + | j < i ) or /* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ - (not ((ExceptFlowNode)this.getAnExceptionalSuccessor()).handles(raised) and - not succ instanceof ExceptFlowNode) + not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) and + not succ instanceof ExceptFlowNode ) } - /** Whether this exceptional exit is viable. That is, is it + /** + * Whether this exceptional exit is viable. That is, is it * plausible that the scope `s` can be exited with exception `raised` * at this point. */ @@ -167,46 +163,48 @@ class RaisingNode extends ControlFlowNode { raised.isLegalExceptionType() and raised = this.getARaisedType() and this.isExceptionalExit(s) and - not ((ExceptFlowNode)this.getAnExceptionalSuccessor()).handles(raised) + not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) } - } /** Is this a sequence or mapping subscript x[i]? */ -private predicate sequence_or_mapping(RaisingNode r) { - r.getNode() instanceof Subscript -} +private predicate sequence_or_mapping(RaisingNode r) { r.getNode() instanceof Subscript } private predicate current_exception(ClassObject ex, BasicBlock b) { exists(RaisingNode r | r.viableExceptionEdge(b.getNode(0), ex) and not b.getNode(0) instanceof ExceptFlowNode ) or - exists(BasicBlock prev | + exists(BasicBlock prev | current_exception(ex, prev) and exists(ControlFlowNode pred, ControlFlowNode succ | - pred = prev.getLastNode() and succ = b.getNode(0) | - pred.getASuccessor() = succ and - (/* Normal control flow */ - not pred.getAnExceptionalSuccessor() = succ or - /* Re-raise the current exception, propagating to the successor */ - pred instanceof ReraisingNode) + pred = prev.getLastNode() and succ = b.getNode(0) + | + pred.getASuccessor() = succ and + ( + /* Normal control flow */ + not pred.getAnExceptionalSuccessor() = succ + or + /* Re-raise the current exception, propagating to the successor */ + pred instanceof ReraisingNode + ) ) ) } private predicate unknown_current_exception(BasicBlock b) { exists(RaisingNode r | - r.raisesUnknownType() and + r.raisesUnknownType() and r.getAnExceptionalSuccessor() = b.getNode(0) and not b.getNode(0) instanceof ExceptFlowNode ) or - exists(BasicBlock prev | + exists(BasicBlock prev | unknown_current_exception(prev) and exists(ControlFlowNode pred, ControlFlowNode succ | - pred = prev.getLastNode() and succ = b.getNode(0) | - pred.getASuccessor() = succ and + pred = prev.getLastNode() and succ = b.getNode(0) + | + pred.getASuccessor() = succ and (not pred.getAnExceptionalSuccessor() = succ or pred instanceof ReraisingNode) ) ) @@ -214,9 +212,10 @@ private predicate unknown_current_exception(BasicBlock b) { /** INTERNAL -- Use FunctionObject.getARaisedType() instead */ predicate scope_raises(ClassObject ex, Scope s) { - exists(BasicBlock b | + exists(BasicBlock b | current_exception(ex, b) and - b.getLastNode().isExceptionalExit(s) | + b.getLastNode().isExceptionalExit(s) + | b.getLastNode() instanceof ReraisingNode ) or @@ -225,9 +224,10 @@ predicate scope_raises(ClassObject ex, Scope s) { /** INTERNAL -- Use FunctionObject.raisesUnknownType() instead */ predicate scope_raises_unknown(Scope s) { - exists(BasicBlock b | - b.getLastNode() instanceof ReraisingNode - and b.getLastNode().isExceptionalExit(s) | + exists(BasicBlock b | + b.getLastNode() instanceof ReraisingNode and + b.getLastNode().isExceptionalExit(s) + | unknown_current_exception(b) ) or @@ -237,95 +237,88 @@ predicate scope_raises_unknown(Scope s) { ) } - /** ControlFlowNode for an 'except' statement. */ class ExceptFlowNode extends ControlFlowNode { - - ExceptFlowNode() { - this.getNode() instanceof ExceptStmt - } + ExceptFlowNode() { this.getNode() instanceof ExceptStmt } ControlFlowNode getType() { exists(ExceptStmt ex | this.getBasicBlock().dominates(result.getBasicBlock()) and - ex = this.getNode() and result = ex.getType().getAFlowNode() + ex = this.getNode() and + result = ex.getType().getAFlowNode() ) } ControlFlowNode getName() { exists(ExceptStmt ex | this.getBasicBlock().dominates(result.getBasicBlock()) and - ex = this.getNode() and result = ex.getName().getAFlowNode() + ex = this.getNode() and + result = ex.getName().getAFlowNode() ) } private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) { this.getType().refersTo(obj, cls, origin) or - exists(Object tup | - this.handledObject_objectapi(tup, theTupleType(), _) | + exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) | element_from_tuple_objectapi(tup).refersTo(obj, cls, origin) ) } - + private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) { val.getClass() = cls and ( this.getType().pointsTo(val, origin) or - exists(TupleValue tup | - this.handledObject(tup, ClassValue::tuple(), _) | + exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) | val = tup.getItem(_) and origin = val.getOrigin() ) ) } /** Gets the inferred type(s) that are handled by this node, splitting tuples if possible. */ - pragma [noinline] + pragma[noinline] predicate handledException_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) { this.handledObject_objectapi(obj, cls, origin) and not cls = theTupleType() or - not exists(this.getNode().(ExceptStmt).getType()) and obj = theBaseExceptionType() and cls = theTypeType() and + not exists(this.getNode().(ExceptStmt).getType()) and + obj = theBaseExceptionType() and + cls = theTypeType() and origin = this } - + /** Gets the inferred type(s) that are handled by this node, splitting tuples if possible. */ - pragma [noinline] + pragma[noinline] predicate handledException(Value val, ClassValue cls, ControlFlowNode origin) { this.handledObject(val, cls, origin) and not cls = ClassValue::tuple() or - not exists(this.getNode().(ExceptStmt).getType()) and val = ClassValue::baseException() and cls = ClassValue::type() and + not exists(this.getNode().(ExceptStmt).getType()) and + val = ClassValue::baseException() and + cls = ClassValue::type() and origin = this } - - /** Whether this `except` handles `cls` */ predicate handles(ClassObject cls) { - exists(ClassObject handled | - this.handledException_objectapi(handled, _, _) | + exists(ClassObject handled | this.handledException_objectapi(handled, _, _) | cls.getAnImproperSuperType() = handled ) } - } private ControlFlowNode element_from_tuple_objectapi(Object tuple) { - exists(Tuple t | - t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode() - ) + exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode()) } -/** A Reraising node is the node at the end of a finally block (on the exceptional branch) +/** + * A Reraising node is the node at the end of a finally block (on the exceptional branch) * that reraises the current exception. */ class ReraisingNode extends RaisingNode { - ReraisingNode() { not this.getNode() instanceof Raise and in_finally(this) and - forall(ControlFlowNode succ | - succ = this.getASuccessor() | + forall(ControlFlowNode succ | succ = this.getASuccessor() | succ = this.getAnExceptionalSuccessor() ) } @@ -337,17 +330,12 @@ class ReraisingNode extends RaisingNode { b.getNode(_) = this ) } - } private predicate in_finally(ControlFlowNode n) { - exists(Stmt f | - exists(Try t | f = t.getAFinalstmt()) | - f = n.getNode() + exists(Stmt f | exists(Try t | f = t.getAFinalstmt()) | + f = n.getNode() or f.containsInScope(n.getNode()) ) } - - - diff --git a/python/ql/src/semmle/python/types/Extensions.qll b/python/ql/src/semmle/python/types/Extensions.qll index b6fb3f519ac..7e1e7c5ab85 100644 --- a/python/ql/src/semmle/python/types/Extensions.qll +++ b/python/ql/src/semmle/python/types/Extensions.qll @@ -1,6 +1,7 @@ -/** This library allows custom extensions to the points-to analysis to incorporate +/** + * This library allows custom extensions to the points-to analysis to incorporate * custom domain knowledge into the points-to analysis. - * + * * This should be considered an advance feature. Modifying the points-to analysis * can cause queries to give strange and misleading results, if not done with care. * @@ -14,71 +15,58 @@ private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext private import semmle.python.objects.TObject private import semmle.python.web.HttpConstants - /* Make ObjectInternal visible to save extra imports in user code */ import semmle.python.objects.ObjectInternal abstract class PointsToExtension extends @py_flow_node { - string toString() { result = "PointsToExtension with missing toString" } abstract predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin); - } - /* Legacy API */ - -/* Custom Facts. This extension mechanism allows you to add custom +/* + * Custom Facts. This extension mechanism allows you to add custom * sources of data to the points-to analysis. */ /** DEPRECATED -- Use PointsToExtension instead */ -deprecated abstract class CustomPointsToFact extends @py_flow_node { - +abstract deprecated class CustomPointsToFact extends @py_flow_node { string toString() { result = "CustomPointsToFact with missing toString" } abstract predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin); - } /* For backwards compatibility */ class FinalCustomPointsToFact = CustomPointsToFact; -deprecated abstract class CustomPointsToOriginFact extends CustomPointsToFact { - +abstract deprecated class CustomPointsToOriginFact extends CustomPointsToFact { abstract predicate pointsTo(Object value, ClassObject cls); override predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) { this.pointsTo(value, cls) and origin = this and context.appliesTo(this) } - } /* Custom points-to fact with inferred class */ -deprecated abstract class CustomPointsToObjectFact extends CustomPointsToFact { - +abstract deprecated class CustomPointsToObjectFact extends CustomPointsToFact { abstract predicate pointsTo(Object value); override predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) { this.pointsTo(value) and cls = simple_types(value) and origin = this and context.appliesTo(this) } - } - /** DEPRECATED -- Unsupported; do not use */ -deprecated abstract class CustomPointsToAttribute extends Object { - - abstract predicate attributePointsTo(string name, Object value, ClassObject cls, ControlFlowNode origin); - +abstract deprecated class CustomPointsToAttribute extends Object { + abstract predicate attributePointsTo( + string name, Object value, ClassObject cls, ControlFlowNode origin + ); } /* An example */ - /** Any variable iterating over range or xrange must be an integer */ class RangeIterationVariableFact extends PointsToExtension { - RangeIterationVariableFact() { exists(For f, ControlFlowNode iterable | iterable.getBasicBlock().dominates(this.(ControlFlowNode).getBasicBlock()) and @@ -96,13 +84,10 @@ class RangeIterationVariableFact extends PointsToExtension { origin = this and context.appliesTo(this) } - } /* bottle module route constants */ - class BottleRoutePointToExtension extends PointsToExtension { - string name; BottleRoutePointToExtension() { @@ -110,7 +95,7 @@ class BottleRoutePointToExtension extends PointsToExtension { defn.getScope().(Module).getName() = "bottle" and this = defn.getValue() and name = defn.(NameNode).getId() - | + | name = "route" or name = httpVerbLower() ) @@ -123,19 +108,19 @@ class BottleRoutePointToExtension extends PointsToExtension { origin = orig.asCfgNodeOrHere(this) ) } - } /* Python 3.6+ regex module constants */ - string short_flag(string flag) { - (flag = "ASCII" or - flag = "IGNORECASE" or - flag = "LOCALE" or - flag = "UNICODE" or - flag = "MULTILINE" or - flag = "TEMPLATE") - and result = flag.prefix(1) + ( + flag = "ASCII" or + flag = "IGNORECASE" or + flag = "LOCALE" or + flag = "UNICODE" or + flag = "MULTILINE" or + flag = "TEMPLATE" + ) and + result = flag.prefix(1) or flag = "DOTALL" and result = "S" or @@ -143,11 +128,11 @@ string short_flag(string flag) { } class ReModulePointToExtension extends PointsToExtension { - string name; ReModulePointToExtension() { - exists(ModuleObjectInternal re | re.getName() = "re" and + exists(ModuleObjectInternal re | + re.getName() = "re" and PointsTo::pointsTo(this.(AttrNode).getObject(name), _, re, _) ) } @@ -158,27 +143,21 @@ class ReModulePointToExtension extends PointsToExtension { sre_constants.getName() = "sre_constants" and sre_constants.attribute("SRE_FLAG_" + flag, value, orig) and origin = orig.asCfgNodeOrHere(this) - ) - and pointsTo_helper(context) - } - - pragma [noinline] - private predicate pointsTo_helper(Context context) { - context.appliesTo(this) + ) and + pointsTo_helper(context) } + pragma[noinline] + private predicate pointsTo_helper(Context context) { context.appliesTo(this) } } private class BackwardCompatiblePointToExtension extends PointsToExtension { - - BackwardCompatiblePointToExtension() { - this instanceof CustomPointsToFact - } + BackwardCompatiblePointToExtension() { this instanceof CustomPointsToFact } override predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin) { exists(Object obj, ClassObject cls | this.(CustomPointsToFact).pointsTo(context, obj, cls, origin) - | + | value.getBuiltin() = obj or obj instanceof ControlFlowNode and @@ -193,13 +172,14 @@ private class BackwardCompatiblePointToExtension extends PointsToExtension { additionalAttribute(owner, name, value, origin) ) } - } -private predicate additionalAttribute(ObjectInternal owner, string name, ObjectInternal value, ControlFlowNode origin) { +private predicate additionalAttribute( + ObjectInternal owner, string name, ObjectInternal value, ControlFlowNode origin +) { exists(Object obj, ClassObject cls | owner.getSource().(CustomPointsToAttribute).attributePointsTo(name, obj, cls, origin) - | + | value.getBuiltin() = obj or obj instanceof ControlFlowNode and @@ -209,4 +189,3 @@ private predicate additionalAttribute(ObjectInternal owner, string name, ObjectI ) ) } - diff --git a/python/ql/src/semmle/python/types/FunctionObject.qll b/python/ql/src/semmle/python/types/FunctionObject.qll index 6c1ed1bf93a..6c1db531184 100644 --- a/python/ql/src/semmle/python/types/FunctionObject.qll +++ b/python/ql/src/semmle/python/types/FunctionObject.qll @@ -9,22 +9,13 @@ private import semmle.python.types.Builtins /** A function object, whether written in Python or builtin */ abstract class FunctionObject extends Object { + CallableValue theCallable() { result.(ObjectInternal).getSource() = this } - CallableValue theCallable() { - result.(ObjectInternal).getSource() = this - } + predicate isOverridingMethod() { exists(Object f | this.overrides(f)) } - predicate isOverridingMethod() { - exists(Object f | this.overrides(f)) - } + predicate isOverriddenMethod() { exists(Object f | f.overrides(this)) } - predicate isOverriddenMethod() { - exists(Object f | f.overrides(this)) - } - - Function getFunction() { - result = ((CallableExpr)this.getOrigin()).getInnerScope() - } + Function getFunction() { result = this.getOrigin().(CallableExpr).getInnerScope() } /** This function always returns None, meaning that its return value should be disregarded */ abstract predicate isProcedure(); @@ -39,17 +30,13 @@ abstract class FunctionObject extends Object { abstract predicate raisesUnknownType(); /** Use descriptiveString() instead. */ - deprecated string prettyString() { - result = this.descriptiveString() - } + deprecated string prettyString() { result = this.descriptiveString() } /** Gets a longer, more descriptive version of toString() */ abstract string descriptiveString(); /** Gets a call-site from where this function is called as a function */ - CallNode getAFunctionCall() { - result.getFunction().inferredValue() = theCallable() - } + CallNode getAFunctionCall() { result.getFunction().inferredValue() = theCallable() } /** Gets a call-site from where this function is called as a method */ CallNode getAMethodCall() { @@ -60,36 +47,36 @@ abstract class FunctionObject extends Object { } /** Gets a call-site from where this function is called */ - ControlFlowNode getACall() { - result = theCallable().getACall() - } + ControlFlowNode getACall() { result = theCallable().getACall() } /** Gets a call-site from where this function is called, given the `context` */ ControlFlowNode getACall(Context caller_context) { result = theCallable().getACall(caller_context) } - /** Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`. + /** + * Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`. * This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument. - */ + */ ControlFlowNode getArgumentForCall(CallNode call, int n) { result = theCallable().getArgumentForCall(call, n) } - /** Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`. + /** + * Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`. * This predicate will correctly handle `x.y()`, treating `x` as the self argument. - */ + */ ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { result = theCallable().getNamedArgumentForCall(call, name) } /** Whether this function never returns. This is an approximation. */ - predicate neverReturns() { - theCallable().neverReturns() - } + predicate neverReturns() { theCallable().neverReturns() } - /** Whether this is a "normal" method, that is, it is exists as a class attribute - * which is not wrapped and not the __new__ method. */ + /** + * Whether this is a "normal" method, that is, it is exists as a class attribute + * which is not wrapped and not the __new__ method. + */ predicate isNormalMethod() { exists(ClassObject cls, string name | cls.declaredAttribute(name) = this and @@ -112,7 +99,8 @@ abstract class FunctionObject extends Object { ) } - /** Gets the qualified name for this function object. + /** + * Gets the qualified name for this function object. * Should return the same name as the `__qualname__` attribute on functions in Python 3. */ abstract string getQualifiedName(); @@ -128,59 +116,39 @@ abstract class FunctionObject extends Object { } /** Gets a class that this function may return */ - ClassObject getAnInferredReturnType() { - result = this.(BuiltinCallable).getAReturnType() - } - - predicate isAbstract() { - this.getARaisedType() = theNotImplementedErrorType() - } + ClassObject getAnInferredReturnType() { result = this.(BuiltinCallable).getAReturnType() } + predicate isAbstract() { this.getARaisedType() = theNotImplementedErrorType() } } class PyFunctionObject extends FunctionObject { + PyFunctionObject() { any(PythonFunctionObjectInternal f).getOrigin() = this } - PyFunctionObject() { - any(PythonFunctionObjectInternal f).getOrigin() = this - } - - override string toString() { - result = "Function " + this.getName() - } + override string toString() { result = "Function " + this.getName() } override string getName() { - result = ((FunctionExpr)this.getOrigin()).getName() + result = this.getOrigin().(FunctionExpr).getName() or this.getOrigin() instanceof Lambda and result = "lambda" } /** Whether this function is a procedure, that is, it has no explicit return statement and is not a generator function */ - override predicate isProcedure() { - this.getFunction().isProcedure() - } + override predicate isProcedure() { this.getFunction().isProcedure() } - override ClassObject getARaisedType() { - scope_raises(result, this.getFunction()) - } + override ClassObject getARaisedType() { scope_raises(result, this.getFunction()) } - override predicate raisesUnknownType() { - scope_raises_unknown(this.getFunction()) - } + override predicate raisesUnknownType() { scope_raises_unknown(this.getFunction()) } /** Gets a control flow node corresponding to the value of a return statement */ - ControlFlowNode getAReturnedNode() { - result = this.getFunction().getAReturnValueFlowNode() - } + ControlFlowNode getAReturnedNode() { result = this.getFunction().getAReturnValueFlowNode() } override string descriptiveString() { - if this.getFunction().isMethod() then ( - exists(Class cls | - this.getFunction().getScope() = cls | + if this.getFunction().isMethod() + then + exists(Class cls | this.getFunction().getScope() = cls | result = "method " + this.getQualifiedName() ) - ) else ( - result = "function " + this.getQualifiedName() - ) + else result = "function " + this.getQualifiedName() } override int minParameters() { @@ -193,16 +161,13 @@ class PyFunctionObject extends FunctionObject { override int maxParameters() { exists(Function f | f = this.getFunction() and - if exists(f.getVararg()) then - result = 2147483647 // INT_MAX - else - result = count(f.getAnArg()) + if exists(f.getVararg()) + then result = 2147483647 // INT_MAX + else result = count(f.getAnArg()) ) } - override string getQualifiedName() { - result = this.getFunction().getQualifiedName() - } + override string getQualifiedName() { result = this.getFunction().getQualifiedName() } predicate unconditionallyReturnsParameter(int n) { exists(SsaVariable pvar | @@ -219,7 +184,9 @@ class PyFunctionObject extends FunctionObject { /** Factored out to help join ordering */ private predicate implicitlyReturns(Object none_, ClassObject noneType) { - noneType = theNoneType() and not this.getFunction().isGenerator() and none_ = theNoneObject() and + noneType = theNoneType() and + not this.getFunction().isGenerator() and + none_ = theNoneObject() and ( not exists(this.getAReturnedNode()) and exists(this.getFunction().getANormalExit()) or @@ -231,9 +198,10 @@ class PyFunctionObject extends FunctionObject { override ClassObject getAnInferredReturnType() { this.getFunction().isGenerator() and result = theGeneratorType() or - not this.neverReturns() and not this.getFunction().isGenerator() and + not this.neverReturns() and + not this.getFunction().isGenerator() and ( - this.(PyFunctionObject).getAReturnedNode().refersTo( _, result, _) + this.(PyFunctionObject).getAReturnedNode().refersTo(_, result, _) or this.implicitlyReturns(_, result) ) @@ -242,18 +210,13 @@ class PyFunctionObject extends FunctionObject { ParameterDefinition getParameter(int n) { result.getDefiningNode().getNode() = this.getFunction().getArg(n) } - } abstract class BuiltinCallable extends FunctionObject { - abstract ClassObject getAReturnType(); override predicate isProcedure() { - forex(ClassObject rt | - rt = this.getAReturnType() | - rt = theNoneType() - ) + forex(ClassObject rt | rt = this.getAReturnType() | rt = theNoneType()) } abstract override string getQualifiedName(); @@ -261,18 +224,13 @@ abstract class BuiltinCallable extends FunctionObject { override ControlFlowNode getArgumentForCall(CallNode call, int n) { call = this.getACall() and result = call.getArg(n) } - } class BuiltinMethodObject extends BuiltinCallable { - - BuiltinMethodObject() { - any(BuiltinMethodObjectInternal m).getBuiltin() = this - } + BuiltinMethodObject() { any(BuiltinMethodObjectInternal m).getBuiltin() = this } override string getQualifiedName() { - exists(ClassObject cls | - cls.asBuiltin().getMember(_) = this.asBuiltin() | + exists(ClassObject cls | cls.asBuiltin().getMember(_) = this.asBuiltin() | result = cls.getName() + "." + this.getName() ) or @@ -280,17 +238,11 @@ class BuiltinMethodObject extends BuiltinCallable { result = this.getName() } - override string descriptiveString() { - result = "builtin-method " + this.getQualifiedName() - } + override string descriptiveString() { result = "builtin-method " + this.getQualifiedName() } - override string getName() { - result = this.asBuiltin().getName() - } + override string getName() { result = this.asBuiltin().getName() } - override string toString() { - result = "Builtin-method " + this.getName() - } + override string toString() { result = "Builtin-method " + this.getName() } override ClassObject getARaisedType() { /* Information is unavailable for C code in general */ @@ -302,41 +254,23 @@ class BuiltinMethodObject extends BuiltinCallable { any() } - override int minParameters() { - none() - } + override int minParameters() { none() } - override int maxParameters() { - none() - } - - override ClassObject getAReturnType() { - ext_rettype(this.asBuiltin(), result.asBuiltin()) - } + override int maxParameters() { none() } + override ClassObject getAReturnType() { ext_rettype(this.asBuiltin(), result.asBuiltin()) } } class BuiltinFunctionObject extends BuiltinCallable { + BuiltinFunctionObject() { any(BuiltinFunctionObjectInternal f).getBuiltin() = this } - BuiltinFunctionObject() { - any(BuiltinFunctionObjectInternal f).getBuiltin() = this - } + override string getName() { result = this.asBuiltin().getName() } - override string getName() { - result = this.asBuiltin().getName() - } + override string getQualifiedName() { result = this.getName() } - override string getQualifiedName() { - result = this.getName() - } + override string toString() { result = "Builtin-function " + this.getName() } - override string toString() { - result = "Builtin-function " + this.getName() - } - - override string descriptiveString() { - result = "builtin-function " + this.getName() - } + override string descriptiveString() { result = "builtin-function " + this.getName() } override ClassObject getARaisedType() { /* Information is unavailable for C code in general */ @@ -349,16 +283,19 @@ class BuiltinFunctionObject extends BuiltinCallable { } override ClassObject getAReturnType() { - /* Enumerate the types of a few builtin functions, that the CPython analysis misses. - */ + /* + * Enumerate the types of a few builtin functions, that the CPython analysis misses. + */ + this = Object::builtin("hex") and result = theStrType() or this = Object::builtin("oct") and result = theStrType() or this = Object::builtin("intern") and result = theStrType() or - /* Fix a few minor inaccuracies in the CPython analysis */ - ext_rettype(this.asBuiltin(), result.asBuiltin()) and not ( + /* Fix a few minor inaccuracies in the CPython analysis */ + ext_rettype(this.asBuiltin(), result.asBuiltin()) and + not ( this = Object::builtin("__import__") and result = theNoneType() or this = Object::builtin("compile") and result = theNoneType() @@ -369,63 +306,37 @@ class BuiltinFunctionObject extends BuiltinCallable { ) } - override int minParameters() { - none() - } - - override int maxParameters() { - none() - } + override int minParameters() { none() } + override int maxParameters() { none() } } /** DEPRECATED -- Use `Object::builtin("apply")` instead. */ -deprecated Object theApplyFunction() { - result = Object::builtin("apply") -} +deprecated Object theApplyFunction() { result = Object::builtin("apply") } /** DEPRECATED -- Use `Object::builtin("hasattr")` instead. */ -deprecated Object theHasattrFunction() { - result = Object::builtin("hasattr") -} +deprecated Object theHasattrFunction() { result = Object::builtin("hasattr") } /** DEPRECATED -- Use `Object::builtin("len")` instead. */ -deprecated Object theLenFunction() { - result = Object::builtin("len") -} +deprecated Object theLenFunction() { result = Object::builtin("len") } /** DEPRECATED -- Use `Object::builtin("format")` instead. */ -deprecated Object theFormatFunction() { - result = Object::builtin("format") -} +deprecated Object theFormatFunction() { result = Object::builtin("format") } /** DEPRECATED -- Use `Object::builtin("open")` instead. */ -deprecated Object theOpenFunction() { - result = Object::builtin("open") -} +deprecated Object theOpenFunction() { result = Object::builtin("open") } /** DEPRECATED -- Use `Object::builtin("print")` instead. */ -deprecated Object thePrintFunction() { - result = Object::builtin("print") -} +deprecated Object thePrintFunction() { result = Object::builtin("print") } /** DEPRECATED -- Use `Object::builtin("input")` instead. */ -deprecated Object theInputFunction() { - result = Object::builtin("input") -} +deprecated Object theInputFunction() { result = Object::builtin("input") } /** DEPRECATED -- Use `Object::builtin("locals")` instead. */ -deprecated Object theLocalsFunction() { - result = Object::builtin("locals") -} +deprecated Object theLocalsFunction() { result = Object::builtin("locals") } /** DEPRECATED -- Use `Object::builtin("globals")()` instead. */ -deprecated Object theGlobalsFunction() { - result = Object::builtin("globals") -} +deprecated Object theGlobalsFunction() { result = Object::builtin("globals") } /** DEPRECATED -- Use `Object::builtin("sysExit()` instead. */ -deprecated Object theExitFunctionObject() { - result = ModuleObject::named("sys").attr("exit") -} - +deprecated Object theExitFunctionObject() { result = ModuleObject::named("sys").attr("exit") } diff --git a/python/ql/src/semmle/python/types/ImportTime.qll b/python/ql/src/semmle/python/types/ImportTime.qll index 0a9e7c9d145..a35ed9d122a 100644 --- a/python/ql/src/semmle/python/types/ImportTime.qll +++ b/python/ql/src/semmle/python/types/ImportTime.qll @@ -1,18 +1,18 @@ import python -/** An ImportTimeScope is any scope that is not nested within a function and will thus be executed if its - * enclosing module is imported. +/** + * An ImportTimeScope is any scope that is not nested within a function and will thus be executed if its + * enclosing module is imported. * Note however, that if a scope is not an ImportTimeScope it may still be executed at import time. * This is an artificial approximation, which is necessary for static analysis. */ class ImportTimeScope extends Scope { - - ImportTimeScope() { - not this.getEnclosingScope*() instanceof Function - } + ImportTimeScope() { not this.getEnclosingScope*() instanceof Function } - /** Whether this scope explicitly defines 'name'. - * Does not cover implicit definitions be import * */ + /** + * Whether this scope explicitly defines 'name'. + * Does not cover implicit definitions be import * + */ pragma[nomagic] predicate definesName(string name) { exists(SsaVariable var | name = var.getId() and var.getAUse() = this.getANormalExit()) @@ -31,5 +31,4 @@ class ImportTimeScope extends Scope { result.getScope() = this.getEnclosingModule() and var.getId() = result.getId() } - } diff --git a/python/ql/src/semmle/python/types/ModuleKind.qll b/python/ql/src/semmle/python/types/ModuleKind.qll index abb39626ff1..1509bac24e2 100644 --- a/python/ql/src/semmle/python/types/ModuleKind.qll +++ b/python/ql/src/semmle/python/types/ModuleKind.qll @@ -11,14 +11,16 @@ private predicate is_normal_module(ModuleObject m) { } private predicate is_script(ModuleObject m) { - not is_normal_module(m) and ( + not is_normal_module(m) and + ( m.getModule().getFile().getExtension() != ".py" or - exists(If i, Name name, StrConst main, Cmpop op | + exists(If i, Name name, StrConst main, Cmpop op | i.getScope() = m.getModule() and op instanceof Eq and i.getTest().(Compare).compares(name, op, main) and - name.getId() = "__name__" and main.getText() = "__main__" + name.getId() = "__name__" and + main.getText() = "__main__" ) ) } @@ -29,7 +31,8 @@ private predicate is_plugin(ModuleObject m) { not is_script(m) } -/** Gets the kind for module `m` will be one of +/** + * Gets the kind for module `m` will be one of * "module", "script" or "plugin" */ string getKindForModule(ModuleObject m) { diff --git a/python/ql/src/semmle/python/types/ModuleObject.qll b/python/ql/src/semmle/python/types/ModuleObject.qll index 0590636edfd..3b5d15c41b1 100644 --- a/python/ql/src/semmle/python/types/ModuleObject.qll +++ b/python/ql/src/semmle/python/types/ModuleObject.qll @@ -4,7 +4,6 @@ private import semmle.python.objects.ObjectInternal private import semmle.python.types.ModuleKind abstract class ModuleObject extends Object { - ModuleValue theModule() { result.(PythonModuleObjectInternal).getSourceModule() = this.getModule() or @@ -14,18 +13,12 @@ abstract class ModuleObject extends Object { } /** Gets the scope corresponding to this module, if this is a Python module */ - Module getModule() { - none() - } + Module getModule() { none() } /** Gets the source scope corresponding to this module, if this is a Python module */ - Module getSourceModule() { - none() - } + Module getSourceModule() { none() } - Container getPath() { - none() - } + Container getPath() { none() } /** Gets the name of this scope */ abstract string getName(); @@ -37,23 +30,20 @@ abstract class ModuleObject extends Object { result = this.getModule().toString() } - /** Gets the named attribute of this module. Using attributeRefersTo() instead + /** + * Gets the named attribute of this module. Using attributeRefersTo() instead * may provide better results for presentation. - * */ - Object getAttribute(string name) { - this.attributeRefersTo(name, result, _) - } + */ + Object getAttribute(string name) { this.attributeRefersTo(name, result, _) } - /** Gets the named attribute of this module. - * Synonym for `getAttribute(name)` */ - pragma [inline] - final Object attr(string name) { - result = this.getAttribute(name) - } + /** + * Gets the named attribute of this module. + * Synonym for `getAttribute(name)` + */ + pragma[inline] + final Object attr(string name) { result = this.getAttribute(name) } - predicate hasAttribute(string name) { - theModule().hasAttribute(name) - } + predicate hasAttribute(string name) { theModule().hasAttribute(name) } predicate attributeRefersTo(string name, Object obj, ControlFlowNode origin) { exists(ObjectInternal val, CfgOrigin valorig | @@ -78,150 +68,111 @@ abstract class ModuleObject extends Object { result.getName() = this.getName().regexpReplaceAll("\\.[^.]*$", "") } - /** Whether this module "exports" `name`. That is, whether using `import *` on this module - * will result in `name` being added to the namespace. */ - predicate exports(string name) { - theModule().exports(name) - } + /** + * Whether this module "exports" `name`. That is, whether using `import *` on this module + * will result in `name` being added to the namespace. + */ + predicate exports(string name) { theModule().exports(name) } /** - * Whether the complete set of names "exported" by this module can be accurately determined - * - * DEPRECATED: Use ModuleValue::hasCompleteExportInfo instead - */ - deprecated abstract predicate exportsComplete(); + * Whether the complete set of names "exported" by this module can be accurately determined + * + * DEPRECATED: Use ModuleValue::hasCompleteExportInfo instead + */ + abstract deprecated predicate exportsComplete(); /** Gets the short name of the module. For example the short name of module x.y.z is 'z' */ string getShortName() { - result = this.getName().suffix(this.getPackage().getName().length()+1) + result = this.getName().suffix(this.getPackage().getName().length() + 1) or result = this.getName() and not exists(this.getPackage()) } - /** Whether this module is imported by 'import name'. For example on a linux system, - * the module 'posixpath' is imported as 'os.path' or as 'posixpath' */ - predicate importedAs(string name) { - PointsToInternal::module_imported_as(theModule(), name) - } + /** + * Whether this module is imported by 'import name'. For example on a linux system, + * the module 'posixpath' is imported as 'os.path' or as 'posixpath' + */ + predicate importedAs(string name) { PointsToInternal::module_imported_as(theModule(), name) } ModuleObject getAnImportedModule() { result.importedAs(this.getModule().getAnImportedModuleName()) } - /** Gets the kind for this module. Will be one of + /** + * Gets the kind for this module. Will be one of * "module", "script" or "plugin". */ - string getKind() { - result = getKindForModule(this) - } - - override boolean booleanValue() { - result = true - } + string getKind() { result = getKindForModule(this) } + override boolean booleanValue() { result = true } } class BuiltinModuleObject extends ModuleObject { + BuiltinModuleObject() { this.asBuiltin().getClass() = theModuleType().asBuiltin() } - BuiltinModuleObject () { - this.asBuiltin().getClass() = theModuleType().asBuiltin() - } - - override string getName() { - result = this.asBuiltin().getName() - } + override string getName() { result = this.asBuiltin().getName() } override Object getAttribute(string name) { result.asBuiltin() = this.asBuiltin().getMember(name) } - override predicate hasAttribute(string name) { - exists(this.asBuiltin().getMember(name)) - } - - override predicate exportsComplete() { - any() - } - + override predicate hasAttribute(string name) { exists(this.asBuiltin().getMember(name)) } + override predicate exportsComplete() { any() } } class PythonModuleObject extends ModuleObject { + PythonModuleObject() { exists(Module m | m.getEntryNode() = this | not m.isPackage()) } - PythonModuleObject() { - exists(Module m | m.getEntryNode() = this | - not m.isPackage() - ) - } + override string getName() { result = this.getModule().getName() } - override string getName() { - result = this.getModule().getName() - } + override Module getModule() { result = this.getOrigin() } - override Module getModule() { - result = this.getOrigin() - } + override Module getSourceModule() { result = this.getOrigin() } - override Module getSourceModule() { - result = this.getOrigin() - } - - override Container getPath() { - result = this.getModule().getFile() - } + override Container getPath() { result = this.getModule().getFile() } override predicate exportsComplete() { - exists(Module m | - m = this.getModule() | - not exists(Call modify, Attribute attr, GlobalVariable all | - modify.getScope() = m and modify.getFunc() = attr and - all.getId() = "__all__" | + exists(Module m | m = this.getModule() | + not exists(Call modify, Attribute attr, GlobalVariable all | + modify.getScope() = m and + modify.getFunc() = attr and + all.getId() = "__all__" + | attr.getObject().(Name).uses(all) ) ) } - } -/** Primarily for internal use. +/** + * Primarily for internal use. * - * Gets the object for the string text. - * The extractor will have populated a str object + * Gets the object for the string text. + * The extractor will have populated a str object * for each module name, with the name b'text' or u'text' (including the quotes). */ Object object_for_string(string text) { result.asBuiltin().getClass() = theStrType().asBuiltin() and exists(string repr | repr = result.asBuiltin().getName() and - repr.charAt(1) = "'" | + repr.charAt(1) = "'" + | /* Strip quotes off repr */ - text = repr.substring(2, repr.length()-1) + text = repr.substring(2, repr.length() - 1) ) } class PackageObject extends ModuleObject { + PackageObject() { exists(Module p | p.getEntryNode() = this | p.isPackage()) } - PackageObject() { - exists(Module p | p.getEntryNode() = this | - p.isPackage() - ) - } + override string getName() { result = this.getModule().getName() } - override string getName() { - result = this.getModule().getName() - } + override Module getModule() { result = this.getOrigin() } - override Module getModule() { - result = this.getOrigin() - } + override Module getSourceModule() { result = this.getModule().getInitModule() } - override Module getSourceModule() { - result = this.getModule().getInitModule() - } - - override Container getPath() { - result = this.getModule().getPath() - } + override Container getPath() { result = this.getModule().getPath() } ModuleObject submodule(string name) { result.getPackage() = this and @@ -235,9 +186,7 @@ class PackageObject extends ModuleObject { ) } - PythonModuleObject getInitModule() { - result.getModule() = this.getModule().getInitModule() - } + PythonModuleObject getInitModule() { result.getModule() = this.getModule().getInitModule() } /** Holds if this package has no `__init__.py` file. */ predicate hasNoInitModule() { @@ -259,23 +208,19 @@ class PackageObject extends ModuleObject { this.getInitModule().hasAttribute(name) } - Location getLocation() { - none() - } + Location getLocation() { none() } override predicate hasLocationInfo(string path, int bl, int bc, int el, int ec) { path = this.getPath().getName() and - bl = 0 and bc = 0 and el = 0 and ec = 0 + bl = 0 and + bc = 0 and + el = 0 and + ec = 0 } - } /** Utility module for predicates relevant to the `ModuleObject` class. */ module ModuleObject { - /** Gets a `ModuleObject` called `name`, if it exists. */ - ModuleObject named(string name) { - result.getName() = name - } - + ModuleObject named(string name) { result.getName() = name } } diff --git a/python/ql/src/semmle/python/types/Object.qll b/python/ql/src/semmle/python/types/Object.qll index fa6512bec5b..f015972d0b6 100644 --- a/python/ql/src/semmle/python/types/Object.qll +++ b/python/ql/src/semmle/python/types/Object.qll @@ -3,7 +3,8 @@ private import semmle.python.objects.ObjectAPI private import semmle.python.objects.ObjectInternal private import semmle.python.types.Builtins -private cached predicate is_an_object(@py_object obj) { +cached +private predicate is_an_object(@py_object obj) { /* CFG nodes for numeric literals, all of which have a @py_cobject for the value of that literal */ obj instanceof ControlFlowNode and not obj.(ControlFlowNode).getNode() instanceof IntegerLiteral and @@ -12,30 +13,30 @@ private cached predicate is_an_object(@py_object obj) { obj instanceof Builtin } -/** Instances of this class represent objects in the Python program. However, since +/** + * Instances of this class represent objects in the Python program. However, since * the QL database is static and Python programs are dynamic, there are necessarily a - * number of approximations. + * number of approximations. * * Each point in the control flow graph where a new object can be created is treated as - * an object. Many builtin objects, such as integers, strings and builtin classes, are - * also treated as 'objects'. Hence each 'object', that is an instance of this class, - * represents a set of actual Python objects in the actual program. + * an object. Many builtin objects, such as integers, strings and builtin classes, are + * also treated as 'objects'. Hence each 'object', that is an instance of this class, + * represents a set of actual Python objects in the actual program. * - * Ideally each set would contain only one member, but that is not possible in practice. - * Many instances of this class will represent many actual Python objects, especially - * if the point in the control flow graph to which they refer is in a loop. Others may not - * refer to any objects. However, for many important objects such as classes and functions, + * Ideally each set would contain only one member, but that is not possible in practice. + * Many instances of this class will represent many actual Python objects, especially + * if the point in the control flow graph to which they refer is in a loop. Others may not + * refer to any objects. However, for many important objects such as classes and functions, * there is a one-to-one relation. */ class Object extends @py_object { + Object() { is_an_object(this) } - Object() { - is_an_object(this) - } - - /** Gets an inferred type for this object, without using inter-procedural analysis. + /** + * Gets an inferred type for this object, without using inter-procedural analysis. * WARNING: The lack of context makes this less accurate than f.refersTo(this, result, _) - * for a control flow node 'f' */ + * for a control flow node 'f' + */ ClassObject getAnInferredType() { exists(ControlFlowNode somewhere | somewhere.refersTo(this, result, _)) or @@ -44,57 +45,57 @@ class Object extends @py_object { this = unknownValue() and result = theUnknownType() } - /** Whether this is a builtin object. A builtin object is one defined by the implementation, - * such as the integer 4 or by a native extension, such as a NumPy array class. */ - predicate isBuiltin() { - exists(this.asBuiltin()) - } + /** + * Whether this is a builtin object. A builtin object is one defined by the implementation, + * such as the integer 4 or by a native extension, such as a NumPy array class. + */ + predicate isBuiltin() { exists(this.asBuiltin()) } /** Retained for backwards compatibility. See Object.isBuiltin() */ - predicate isC() { - this.isBuiltin() - } + predicate isC() { this.isBuiltin() } - /** Gets the point in the source code from which this object "originates". + /** + * Gets the point in the source code from which this object "originates". * * WARNING: The lack of context makes this less accurate than f.refersTo(this, _, result) * for a control flow node 'f'. */ - AstNode getOrigin() { - py_flow_bb_node(this, result, _, _) - } + AstNode getOrigin() { py_flow_bb_node(this, result, _, _) } - private predicate hasOrigin() { - py_flow_bb_node(this, _, _, _) - } + private predicate hasOrigin() { py_flow_bb_node(this, _, _, _) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.hasOrigin() and this.getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec) or - not this.hasOrigin() and filepath = ":Compiled Code" and bl = 0 and bc = 0 and el = 0 and ec = 0 + not this.hasOrigin() and + filepath = ":Compiled Code" and + bl = 0 and + bc = 0 and + el = 0 and + ec = 0 } /** INTERNAL -- Do not use */ - Builtin asBuiltin() { - result = this - } + Builtin asBuiltin() { result = this } string toString() { - not this = undefinedVariable() and not this = unknownValue() and - exists(ClassObject type | - type.asBuiltin() = this.asBuiltin().getClass() | + not this = undefinedVariable() and + not this = unknownValue() and + exists(ClassObject type | type.asBuiltin() = this.asBuiltin().getClass() | result = type.getName() + " " + this.asBuiltin().getName() ) or result = this.getOrigin().toString() } - /** Gets the class of this object for simple cases, namely constants, functions, + /** + * Gets the class of this object for simple cases, namely constants, functions, * comprehensions and built-in objects. * * This exists primarily for internal use. Use getAnInferredType() instead. */ - cached ClassObject simpleClass() { + cached + ClassObject simpleClass() { result = comprehension(this.getOrigin()) or result = collection_literal(this.getOrigin()) @@ -108,29 +109,23 @@ class Object extends @py_object { result.(Object).asBuiltin() = this.asBuiltin().getClass() } - private - ClassObject declaringClass(string name) { - result.declaredAttribute(name) = this - } + private ClassObject declaringClass(string name) { result.declaredAttribute(name) = this } - /** Whether this overrides o. In this context, "overrides" means that this object + /** + * Whether this overrides o. In this context, "overrides" means that this object * is a named attribute of a some class C and `o` is a named attribute of another * class S, both attributes having the same name, and S is a super class of C. */ predicate overrides(Object o) { - exists(string name | - declaringClass(name).getASuperType() = o.declaringClass(name) - ) + exists(string name | declaringClass(name).getASuperType() = o.declaringClass(name)) } private boolean booleanFromValue() { - exists(ObjectInternal obj | - obj.getSource() = this | - result = obj.booleanValue() - ) + exists(ObjectInternal obj | obj.getSource() = this | result = obj.booleanValue()) } - /** The Boolean value of this object if it always evaluates to true or false. + /** + * The Boolean value of this object if it always evaluates to true or false. * For example: * false for None, true for 7 and no result for int(x) */ @@ -144,22 +139,26 @@ class Object extends @py_object { booleanFromValue() = false } - predicate notClass() { - any() - } + predicate notClass() { any() } - /** Holds if this object can be referred to by `longName` + /** + * Holds if this object can be referred to by `longName` * For example, the modules `dict` in the `sys` module * has the long name `sys.modules` and the name `os.path.join` * will refer to the path joining function even though it might * be declared in the `posix` or `nt` modules. * Long names can have no more than three dots after the module name. */ - cached predicate hasLongName(string longName) { - this = findByName0(longName) or - this = findByName1(longName) or - this = findByName2(longName) or - this = findByName3(longName) or + cached + predicate hasLongName(string longName) { + this = findByName0(longName) + or + this = findByName1(longName) + or + this = findByName2(longName) + or + this = findByName3(longName) + or exists(ClassMethodObject cm | cm.hasLongName(longName) and cm.getFunction() = this @@ -170,64 +169,54 @@ class Object extends @py_object { cm.getFunction() = this ) } - } -private Object findByName0(string longName) { - result.(ModuleObject).getName() = longName -} +private Object findByName0(string longName) { result.(ModuleObject).getName() = longName } private Object findByName1(string longName) { - exists(string owner, string attrname | - longName = owner + "." + attrname - | + exists(string owner, string attrname | longName = owner + "." + attrname | result = findByName0(owner).(ModuleObject).attr(attrname) or result = findByName0(owner).(ClassObject).lookupAttribute(attrname) - ) - and + ) and not result = findByName0(_) } private Object findByName2(string longName) { - exists(string owner, string attrname | - longName = owner + "." + attrname - | + exists(string owner, string attrname | longName = owner + "." + attrname | result = findByName1(owner).(ModuleObject).attr(attrname) or result = findByName1(owner).(ClassObject).lookupAttribute(attrname) - ) - and not result = findByName0(_) - and not result = findByName1(_) + ) and + not result = findByName0(_) and + not result = findByName1(_) } private Object findByName3(string longName) { - exists(string owner, string attrname | - longName = owner + "." + attrname - | + exists(string owner, string attrname | longName = owner + "." + attrname | result = findByName2(owner).(ModuleObject).attr(attrname) or result = findByName2(owner).(ClassObject).lookupAttribute(attrname) - ) - and not result = findByName0(_) - and not result = findByName1(_) - and not result = findByName2(_) + ) and + not result = findByName0(_) and + not result = findByName1(_) and + not result = findByName2(_) } - -/** Numeric objects (ints and floats). +/** + * Numeric objects (ints and floats). * Includes those occurring in the source as a literal * or in a builtin module as a value. */ class NumericObject extends Object { - NumericObject() { this.asBuiltin().getClass() = theIntType().asBuiltin() or this.asBuiltin().getClass() = theLongType().asBuiltin() or this.asBuiltin().getClass() = theFloatType().asBuiltin() } - /** Gets the Boolean value that this object + /** + * Gets the Boolean value that this object * would evaluate to in a Boolean context, * such as `bool(x)` or `if x: ...` */ @@ -241,51 +230,44 @@ class NumericObject extends Object { this.floatValue() = 0 and result = false } - /** Gets the value of this object if it is a constant integer and it fits in a QL int */ + /** Gets the value of this object if it is a constant integer and it fits in a QL int */ int intValue() { ( this.asBuiltin().getClass() = theIntType().asBuiltin() or this.asBuiltin().getClass() = theLongType().asBuiltin() - ) - and + ) and result = this.asBuiltin().getName().toInt() } - /** Gets the value of this object if it is a constant float */ + /** Gets the value of this object if it is a constant float */ float floatValue() { - this.asBuiltin().getClass() = theFloatType().asBuiltin() - and + this.asBuiltin().getClass() = theFloatType().asBuiltin() and result = this.asBuiltin().getName().toFloat() } /** Gets the string representation of this object, equivalent to calling repr() in Python */ string repr() { - exists(string s | - s = this.asBuiltin().getName() | - if this.asBuiltin().getClass() = theLongType().asBuiltin() then - result = s + "L" - else - result = s + exists(string s | s = this.asBuiltin().getName() | + if this.asBuiltin().getClass() = theLongType().asBuiltin() + then result = s + "L" + else result = s ) } - } -/** String objects (unicode or bytes). +/** + * String objects (unicode or bytes). * Includes those occurring in the source as a literal * or in a builtin module as a value. */ class StringObject extends Object { - StringObject() { this.asBuiltin().getClass() = theUnicodeType().asBuiltin() or this.asBuiltin().getClass() = theBytesType().asBuiltin() } /** Whether this string is composed entirely of ascii encodable characters */ - predicate isAscii() { - this.getText().regexpMatch("^\\p{ASCII}*$") - } + predicate isAscii() { this.getText().regexpMatch("^\\p{ASCII}*$") } override boolean booleanValue() { this.getText() = "" and result = false @@ -294,22 +276,21 @@ class StringObject extends Object { } /** Gets the text for this string */ - cached string getText() { + cached + string getText() { exists(string quoted_string | - quoted_string = this.asBuiltin().getName() - and + quoted_string = this.asBuiltin().getName() and result = quoted_string.regexpCapture("[bu]'([\\s\\S]*)'", 1) ) } - } -/** Sequence objects (lists and tuples) +/** + * Sequence objects (lists and tuples) * Includes those occurring in the source as a literal * or in a builtin module as a value. */ abstract class SequenceObject extends Object { - /** Gets the length of this sequence */ int getLength() { result = strictcount(this.getBuiltinElement(_)) @@ -318,25 +299,19 @@ abstract class SequenceObject extends Object { } /** Gets the nth item of this builtin sequence */ - Object getBuiltinElement(int n) { - result.asBuiltin() = this.asBuiltin().getItem(n) - } + Object getBuiltinElement(int n) { result.asBuiltin() = this.asBuiltin().getItem(n) } /** Gets the nth source element of this sequence */ - ControlFlowNode getSourceElement(int n) { - result = this.(SequenceNode).getElement(n) - } + ControlFlowNode getSourceElement(int n) { result = this.(SequenceNode).getElement(n) } Object getInferredElement(int n) { result = this.getBuiltinElement(n) or this.getSourceElement(n).refersTo(result) } - } class TupleObject extends SequenceObject { - TupleObject() { this.asBuiltin().getClass() = theTupleType().asBuiltin() or @@ -344,118 +319,73 @@ class TupleObject extends SequenceObject { or exists(Function func | func.getVararg().getAFlowNode() = this) } - } module TupleObject { - TupleObject empty() { exists(Builtin empty | empty = result.asBuiltin() and - empty.getClass() = theTupleType().asBuiltin() and + empty.getClass() = theTupleType().asBuiltin() and not exists(empty.getItem(_)) ) } - } class NonEmptyTupleObject extends TupleObject { + NonEmptyTupleObject() { exists(Function func | func.getVararg().getAFlowNode() = this) } - NonEmptyTupleObject() { - exists(Function func | func.getVararg().getAFlowNode() = this) - } - - override boolean booleanValue() { - result = true - } - + override boolean booleanValue() { result = true } } - class ListObject extends SequenceObject { - ListObject() { this.asBuiltin().getClass() = theListType().asBuiltin() or this instanceof ListNode } - } /** The `builtin` module */ -BuiltinModuleObject theBuiltinModuleObject() { - result.asBuiltin() = Builtin::builtinModule() -} +BuiltinModuleObject theBuiltinModuleObject() { result.asBuiltin() = Builtin::builtinModule() } /** The `sys` module */ -BuiltinModuleObject theSysModuleObject() { - result.asBuiltin() = Builtin::special("sys") -} +BuiltinModuleObject theSysModuleObject() { result.asBuiltin() = Builtin::special("sys") } /** DEPRECATED -- Use `Object::builtin(name)` instead. */ -deprecated -Object builtin_object(string name) { - result = Object::builtin(name) -} +deprecated Object builtin_object(string name) { result = Object::builtin(name) } /** The built-in object None */ -Object theNoneObject() { - result.asBuiltin() = Builtin::special("None") -} +Object theNoneObject() { result.asBuiltin() = Builtin::special("None") } /** The built-in object True */ -Object theTrueObject() { - result.asBuiltin() = Builtin::special("True") -} +Object theTrueObject() { result.asBuiltin() = Builtin::special("True") } /** The built-in object False */ -Object theFalseObject() { - result.asBuiltin() = Builtin::special("False") -} +Object theFalseObject() { result.asBuiltin() = Builtin::special("False") } /** The NameError class */ -Object theNameErrorType() { - result = Object::builtin("NameError") -} +Object theNameErrorType() { result = Object::builtin("NameError") } /** The StandardError class */ -Object theStandardErrorType() { - result = Object::builtin("StandardError") -} +Object theStandardErrorType() { result = Object::builtin("StandardError") } /** The IndexError class */ -Object theIndexErrorType() { - result = Object::builtin("IndexError") -} +Object theIndexErrorType() { result = Object::builtin("IndexError") } /** The LookupError class */ -Object theLookupErrorType() { - result = Object::builtin("LookupError") -} +Object theLookupErrorType() { result = Object::builtin("LookupError") } /** DEPRECATED -- Use `Object::quitter(name)` instead. */ -deprecated -Object quitterObject(string name) { - result = Object::quitter(name) -} +deprecated Object quitterObject(string name) { result = Object::quitter(name) } /** DEPRECATED -- Use `Object::notImplemented()` instead. */ -deprecated -Object theNotImplementedObject() { - result = Object::builtin("NotImplemented") -} +deprecated Object theNotImplementedObject() { result = Object::builtin("NotImplemented") } /** DEPRECATED -- Use `TupleObject::empty()` instead. */ -deprecated -Object theEmptyTupleObject() { - result = TupleObject::empty() -} +deprecated Object theEmptyTupleObject() { result = TupleObject::empty() } module Object { - - Object builtin(string name) { - result.asBuiltin() = Builtin::builtin(name) - } + Object builtin(string name) { result.asBuiltin() = Builtin::builtin(name) } /** The named quitter object (quit or exit) in the builtin namespace */ Object quitter(string name) { @@ -464,13 +394,9 @@ module Object { } /** The builtin object `NotImplemented`. Not be confused with `NotImplementedError`. */ - Object notImplemented() { - result = builtin("NotImplemented") - } - + Object notImplemented() { result = builtin("NotImplemented") } } - private ClassObject comprehension(Expr e) { e instanceof ListComp and result = theListType() or @@ -497,23 +423,17 @@ private ClassObject string_literal(Expr e) { e instanceof Unicode and result = theUnicodeType() } -Object theUnknownType() { - result.asBuiltin() = Builtin::unknownType() -} +Object theUnknownType() { result.asBuiltin() = Builtin::unknownType() } /* For backwards compatibility */ - class SuperBoundMethod extends Object { - string name; SuperBoundMethod() { this.(AttrNode).getObject(name).inferredValue().getClass() = Value::named("super") } - override string toString() { - result = "super()." + name - } + override string toString() { result = "super()." + name } Object getFunction(string fname) { fname = name and @@ -523,7 +443,4 @@ class SuperBoundMethod extends Object { result = m.getFunction().getSource() ) } - } - - diff --git a/python/ql/src/semmle/python/types/Properties.qll b/python/ql/src/semmle/python/types/Properties.qll index b0b14262590..207562c63c6 100644 --- a/python/ql/src/semmle/python/types/Properties.qll +++ b/python/ql/src/semmle/python/types/Properties.qll @@ -1,14 +1,14 @@ import python -/** A Python property: - * @property - * def f(): +/** + * A Python property: + * + * @property def f(): * .... * * Also any instances of types.GetSetDescriptorType (which are equivalent, but implemented in C) */ abstract class PropertyObject extends Object { - PropertyObject() { property_getter(this, _) or @@ -27,118 +27,82 @@ abstract class PropertyObject extends Object { /** Gets the deleter of this property */ abstract Object getDeleter(); - override string toString() { - result = "Property " + this.getName() - } + override string toString() { result = "Property " + this.getName() } /** Whether this property is read-only. */ - predicate isReadOnly() { - not exists(this.getSetter()) - } + predicate isReadOnly() { not exists(this.getSetter()) } - /** Gets an inferred type of this property. + /** + * Gets an inferred type of this property. * That is the type returned by its getter function, - * not the type of the property object which is types.PropertyType. */ + * not the type of the property object which is types.PropertyType. + */ abstract ClassObject getInferredPropertyType(); - } - class PythonPropertyObject extends PropertyObject { + PythonPropertyObject() { property_getter(this, _) } - PythonPropertyObject() { - property_getter(this, _) - } - - override string getName() { - result = this.getGetter().getName() - } + override string getName() { result = this.getGetter().getName() } /** Gets the getter function of this property */ - override FunctionObject getGetter() { - property_getter(this, result) - } + override FunctionObject getGetter() { property_getter(this, result) } override ClassObject getInferredPropertyType() { result = this.getGetter().getAnInferredReturnType() } /** Gets the setter function of this property */ - override FunctionObject getSetter() { - property_setter(this, result) - } + override FunctionObject getSetter() { property_setter(this, result) } /** Gets the deleter function of this property */ - override FunctionObject getDeleter() { - property_deleter(this, result) - } - + override FunctionObject getDeleter() { property_deleter(this, result) } } class BuiltinPropertyObject extends PropertyObject { + BuiltinPropertyObject() { this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin() } - BuiltinPropertyObject() { - this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin() - } - - override string getName() { - result = this.asBuiltin().getName() - } + override string getName() { result = this.asBuiltin().getName() } /** Gets the getter method wrapper of this property */ - override Object getGetter() { - result.asBuiltin() = this.asBuiltin().getMember("__get__") - } + override Object getGetter() { result.asBuiltin() = this.asBuiltin().getMember("__get__") } - override ClassObject getInferredPropertyType() { - none() - } + override ClassObject getInferredPropertyType() { none() } /** Gets the setter method wrapper of this property */ - override Object getSetter() { - result.asBuiltin() = this.asBuiltin().getMember("__set__") - } + override Object getSetter() { result.asBuiltin() = this.asBuiltin().getMember("__set__") } /** Gets the deleter method wrapper of this property */ - override Object getDeleter() { - result.asBuiltin() = this.asBuiltin().getMember("__delete__") - } - + override Object getDeleter() { result.asBuiltin() = this.asBuiltin().getMember("__delete__") } } private predicate property_getter(CallNode decorated, FunctionObject getter) { - decorated.getFunction().refersTo(thePropertyType()) - and + decorated.getFunction().refersTo(thePropertyType()) and decorated.getArg(0).refersTo(getter) } private predicate property_setter(CallNode decorated, FunctionObject setter) { - property_getter(decorated, _) - and + property_getter(decorated, _) and exists(CallNode setter_call, AttrNode prop_setter | - prop_setter.getObject("setter").refersTo((Object)decorated) | - setter_call.getArg(0).refersTo(setter) - and + prop_setter.getObject("setter").refersTo(decorated.(Object)) + | + setter_call.getArg(0).refersTo(setter) and setter_call.getFunction() = prop_setter ) or - decorated.getFunction().refersTo(thePropertyType()) - and + decorated.getFunction().refersTo(thePropertyType()) and decorated.getArg(1).refersTo(setter) } private predicate property_deleter(CallNode decorated, FunctionObject deleter) { - property_getter(decorated, _) - and + property_getter(decorated, _) and exists(CallNode deleter_call, AttrNode prop_deleter | - prop_deleter.getObject("deleter").refersTo((Object)decorated) | - deleter_call.getArg(0).refersTo(deleter) - and + prop_deleter.getObject("deleter").refersTo(decorated.(Object)) + | + deleter_call.getArg(0).refersTo(deleter) and deleter_call.getFunction() = prop_deleter ) or - decorated.getFunction().refersTo(thePropertyType()) - and + decorated.getFunction().refersTo(thePropertyType()) and decorated.getArg(2).refersTo(deleter) } - diff --git a/python/ql/src/semmle/python/types/Version.qll b/python/ql/src/semmle/python/types/Version.qll index c55f0ea459c..26ab46e970a 100644 --- a/python/ql/src/semmle/python/types/Version.qll +++ b/python/ql/src/semmle/python/types/Version.qll @@ -1,18 +1,16 @@ import python -/** A Version of the Python interpreter. - * Currently only 2.7 or 3.x but may include different sets of versions in the future. */ +/** + * A Version of the Python interpreter. + * Currently only 2.7 or 3.x but may include different sets of versions in the future. + */ class Version extends int { - - Version() { - this = 2 or this = 3 - } + Version() { this = 2 or this = 3 } /** Holds if this version (or set of versions) includes the version `major`.`minor` */ predicate includes(int major, int minor) { this = 2 and major = 2 and minor = 7 or - this = 3 and major = 3 and minor in [4..8] + this = 3 and major = 3 and minor in [4 .. 8] } - } From f406a45ce00c47035a3f994e3b3add99299732db Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:38:27 +0100 Subject: [PATCH 113/459] Python: Autoformat `web`. --- python/ql/src/semmle/python/web/Http.qll | 93 +++++++------------ .../src/semmle/python/web/HttpConstants.qll | 14 +-- .../ql/src/semmle/python/web/HttpRedirect.qll | 2 - .../src/semmle/python/web/django/General.qll | 6 +- .../src/semmle/python/web/django/Request.qll | 5 +- .../src/semmle/python/web/falcon/General.qll | 3 +- .../src/semmle/python/web/tornado/Tornado.qll | 10 +- .../src/semmle/python/web/webob/Request.qll | 23 +---- 8 files changed, 56 insertions(+), 100 deletions(-) diff --git a/python/ql/src/semmle/python/web/Http.qll b/python/ql/src/semmle/python/web/Http.qll index e12cb6abe96..566d2e11fc4 100644 --- a/python/ql/src/semmle/python/web/Http.qll +++ b/python/ql/src/semmle/python/web/Http.qll @@ -4,15 +4,13 @@ import semmle.python.security.strings.External import HttpConstants /** Generic taint source from a http request */ -abstract class HttpRequestTaintSource extends TaintSource { +abstract class HttpRequestTaintSource extends TaintSource { } -} - -/** Taint kind representing the WSGI environment. +/** + * Taint kind representing the WSGI environment. * As specified in PEP 3333. https://www.python.org/dev/peps/pep-3333/#environ-variables */ class WsgiEnvironment extends TaintKind { - WsgiEnvironment() { this = "wsgi.environment" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { @@ -26,10 +24,12 @@ class WsgiEnvironment extends TaintKind { tonode.(CallNode).getFunction().(AttrNode).getObject("get") = fromnode and tonode.(CallNode).getArg(0).pointsTo(key) or - tonode.(SubscriptNode).getObject() = fromnode and tonode.isLoad() and + tonode.(SubscriptNode).getObject() = fromnode and + tonode.isLoad() and tonode.(SubscriptNode).getIndex().pointsTo(key) - | - key = Value::forString(text) and result instanceof ExternalStringKind and + | + key = Value::forString(text) and + result instanceof ExternalStringKind and ( text = "QUERY_STRING" or text = "PATH_INFO" or @@ -37,96 +37,73 @@ class WsgiEnvironment extends TaintKind { ) ) } - } -/** A standard morsel object from a HTTP request, a value in a cookie, - * typically an instance of `http.cookies.Morsel` */ +/** + * A standard morsel object from a HTTP request, a value in a cookie, + * typically an instance of `http.cookies.Morsel` + */ class UntrustedMorsel extends TaintKind { - - UntrustedMorsel() { - this = "http.Morsel" - } - + UntrustedMorsel() { this = "http.Morsel" } override TaintKind getTaintOfAttribute(string name) { result instanceof ExternalStringKind and - ( - name = "value" - ) + name = "value" } - } /** A standard cookie object from a HTTP request, typically an instance of `http.cookies.SimpleCookie` */ class UntrustedCookie extends TaintKind { - - UntrustedCookie() { - this = "http.Cookie" - } + UntrustedCookie() { this = "http.Cookie" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { tonode.(SubscriptNode).getObject() = fromnode and result instanceof UntrustedMorsel } - } abstract class CookieOperation extends @py_flow_node { - abstract string toString(); abstract ControlFlowNode getKey(); abstract ControlFlowNode getValue(); - } -abstract class CookieGet extends CookieOperation {} +abstract class CookieGet extends CookieOperation { } -abstract class CookieSet extends CookieOperation {} +abstract class CookieSet extends CookieOperation { } /** Generic taint sink in a http response */ abstract class HttpResponseTaintSink extends TaintSink { - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } abstract class HttpRedirectTaintSink extends TaintSink { - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } module Client { - // TODO: user-input in other than URL: // - `data`, `json` for `requests.post` // - `body` for `HTTPConnection.request` // - headers? - // TODO: Add more library support // - urllib3 https://github.com/urllib3/urllib3 // - httpx https://github.com/encode/httpx - /** - * An outgoing http request - * - * For example: - * conn = HTTPConnection('example.com') - conn.request('GET', '/path') - */ + * An outgoing http request + * + * For example: + * conn = HTTPConnection('example.com') + * conn.request('GET', '/path') + */ abstract class HttpRequest extends ControlFlowNode { - - /** Get any ControlFlowNode that is used to construct the final URL. - * - * In the HTTPConnection example, there is a result for both `'example.com'` and for `'/path'`. - */ + /** + * Get any ControlFlowNode that is used to construct the final URL. + * + * In the HTTPConnection example, there is a result for both `'example.com'` and for `'/path'`. + */ abstract ControlFlowNode getAUrlPart(); abstract string getMethodUpper(); @@ -134,14 +111,8 @@ module Client { /** Taint sink for the URL-part of an outgoing http request */ class HttpRequestUrlTaintSink extends TaintSink { + HttpRequestUrlTaintSink() { this = any(HttpRequest r).getAUrlPart() } - HttpRequestUrlTaintSink() { - this = any(HttpRequest r).getAUrlPart() - } - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } } diff --git a/python/ql/src/semmle/python/web/HttpConstants.qll b/python/ql/src/semmle/python/web/HttpConstants.qll index a20b89f9f63..41f3905b887 100644 --- a/python/ql/src/semmle/python/web/HttpConstants.qll +++ b/python/ql/src/semmle/python/web/HttpConstants.qll @@ -1,13 +1,13 @@ - /** Gets an http verb */ string httpVerb() { - result = "GET" or result = "POST" or - result = "PUT" or result = "PATCH" or - result = "DELETE" or result = "OPTIONS" or + result = "GET" or + result = "POST" or + result = "PUT" or + result = "PATCH" or + result = "DELETE" or + result = "OPTIONS" or result = "HEAD" } /** Gets an http verb, in lower case */ -string httpVerbLower() { - result = httpVerb().toLowerCase() -} +string httpVerbLower() { result = httpVerb().toLowerCase() } diff --git a/python/ql/src/semmle/python/web/HttpRedirect.qll b/python/ql/src/semmle/python/web/HttpRedirect.qll index e77f0841195..cfbe35f30f1 100644 --- a/python/ql/src/semmle/python/web/HttpRedirect.qll +++ b/python/ql/src/semmle/python/web/HttpRedirect.qll @@ -1,7 +1,5 @@ import python - import semmle.python.security.strings.Basic - import semmle.python.web.django.Redirect import semmle.python.web.flask.Redirect import semmle.python.web.tornado.Redirect diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll index 423d853cdad..80f63f71974 100644 --- a/python/ql/src/semmle/python/web/django/General.qll +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -27,9 +27,9 @@ class DjangoRoute extends CallNode { } /** - * Get the number of positional arguments that will be passed to the view. - * Will only return a result if there are no named arguments. - */ + * Get the number of positional arguments that will be passed to the view. + * Will only return a result if there are no named arguments. + */ int getNumPositionalArguments() { exists(DjangoRouteRegex regex | django_route(this, regex.getAFlowNode(), _) and diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index cd1bccd5f7f..3523b80268b 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -79,14 +79,13 @@ class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { /** An argument specified in a url routing table */ class DjangoRequestParameter extends HttpRequestTaintSource { DjangoRequestParameter() { - exists(DjangoRoute route, Function f | - f = route.getViewFunction().getScope() | + exists(DjangoRoute route, Function f | f = route.getViewFunction().getScope() | this.(ControlFlowNode).getNode() = f.getArgByName(route.getNamedArgument()) or exists(int i | i >= 0 | i < route.getNumPositionalArguments() and // +1 because first argument is always the request - this.(ControlFlowNode).getNode() = f.getArg(i+1) + this.(ControlFlowNode).getNode() = f.getArg(i + 1) ) ) } diff --git a/python/ql/src/semmle/python/web/falcon/General.qll b/python/ql/src/semmle/python/web/falcon/General.qll index 4c0b347ba38..bee0ad746f6 100644 --- a/python/ql/src/semmle/python/web/falcon/General.qll +++ b/python/ql/src/semmle/python/web/falcon/General.qll @@ -6,7 +6,8 @@ ClassValue theFalconAPIClass() { result = Value::named("falcon.API") } /** Holds if `route` is routed to `resource` */ private predicate api_route(CallNode route_call, ControlFlowNode route, ClassValue resource) { - route_call.getFunction().(AttrNode).getObject("add_route").pointsTo().getClass() = theFalconAPIClass() and + route_call.getFunction().(AttrNode).getObject("add_route").pointsTo().getClass() = + theFalconAPIClass() and route_call.getArg(0) = route and route_call.getArg(1).pointsTo().getClass() = resource } diff --git a/python/ql/src/semmle/python/web/tornado/Tornado.qll b/python/ql/src/semmle/python/web/tornado/Tornado.qll index bf2e0260428..10a5c5be962 100644 --- a/python/ql/src/semmle/python/web/tornado/Tornado.qll +++ b/python/ql/src/semmle/python/web/tornado/Tornado.qll @@ -18,11 +18,11 @@ predicate isTornadoRequestHandlerInstance(ControlFlowNode node) { node.pointsTo().getClass() = aTornadoRequestHandlerClass() or /* - * In some cases, the points-to analysis won't capture all instances we care - * about. For these, we use the following syntactic check. First, that - * `node` appears inside a method of a subclass of - * `tornado.web.RequestHandler`: - */ + * In some cases, the points-to analysis won't capture all instances we care + * about. For these, we use the following syntactic check. First, that + * `node` appears inside a method of a subclass of + * `tornado.web.RequestHandler`: + */ node.getScope().getEnclosingScope() = aTornadoRequestHandlerClass().getScope() and /* Secondly, that `node` refers to the `self` argument: */ diff --git a/python/ql/src/semmle/python/web/webob/Request.qll b/python/ql/src/semmle/python/web/webob/Request.qll index 1662313e0b9..70fa311f6b0 100644 --- a/python/ql/src/semmle/python/web/webob/Request.qll +++ b/python/ql/src/semmle/python/web/webob/Request.qll @@ -1,10 +1,8 @@ import python - import semmle.python.security.TaintTracking import semmle.python.web.Http abstract class BaseWebobRequest extends TaintKind { - bindingset[this] BaseWebobRequest() { any() } @@ -17,9 +15,7 @@ abstract class BaseWebobRequest extends TaintKind { ) or result instanceof ExternalStringKind and - ( - name = "body" - ) + name = "body" } override TaintKind getTaintOfMethodResult(string name) { @@ -30,22 +26,13 @@ abstract class BaseWebobRequest extends TaintKind { name = "copy_body" ) or - result instanceof ExternalStringKind and - ( - name = "as_bytes" - ) + result instanceof ExternalStringKind and + name = "as_bytes" } - } class WebobRequest extends BaseWebobRequest { + WebobRequest() { this = "webob.Request" } - WebobRequest() { - this = "webob.Request" - } - - override ClassValue getType() { - result = Value::named("webob.request.Request") - } - + override ClassValue getType() { result = Value::named("webob.request.Request") } } From 810e91ea00378ddee0a9a5c73840e3a37e0e369e Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:41:45 +0100 Subject: [PATCH 114/459] Python: Autoformat `semmle/python` top-level. --- python/ql/src/semmle/python/AstExtended.qll | 185 +- python/ql/src/semmle/python/AstGenerated.qll | 2266 ++++------------- python/ql/src/semmle/python/Class.qll | 171 +- python/ql/src/semmle/python/Comment.qll | 81 +- python/ql/src/semmle/python/Comparisons.qll | 235 +- .../ql/src/semmle/python/Comprehensions.qll | 84 +- python/ql/src/semmle/python/Constants.qll | 17 +- python/ql/src/semmle/python/Exprs.qll | 627 ++--- python/ql/src/semmle/python/Files.qll | 244 +- python/ql/src/semmle/python/Flow.qll | 747 +++--- python/ql/src/semmle/python/Function.qll | 252 +- .../src/semmle/python/GuardedControlFlow.qll | 32 +- python/ql/src/semmle/python/Import.qll | 188 +- python/ql/src/semmle/python/Keywords.qll | 79 +- python/ql/src/semmle/python/Metrics.qll | 374 ++- python/ql/src/semmle/python/Module.qll | 148 +- python/ql/src/semmle/python/Operations.qll | 171 +- python/ql/src/semmle/python/SSA.qll | 123 +- python/ql/src/semmle/python/Scope.qll | 118 +- python/ql/src/semmle/python/SelfAttribute.qll | 54 +- python/ql/src/semmle/python/Stmts.qll | 338 +-- python/ql/src/semmle/python/TestUtils.qll | 33 +- python/ql/src/semmle/python/Variables.qll | 92 +- 23 files changed, 1984 insertions(+), 4675 deletions(-) diff --git a/python/ql/src/semmle/python/AstExtended.qll b/python/ql/src/semmle/python/AstExtended.qll index 65bc653bfd5..8a858c5fefc 100644 --- a/python/ql/src/semmle/python/AstExtended.qll +++ b/python/ql/src/semmle/python/AstExtended.qll @@ -2,55 +2,52 @@ import python /** Syntactic node (Class, Function, Module, Expr, Stmt or Comprehension) corresponding to a flow node */ abstract class AstNode extends AstNode_ { - - /* Special comment for documentation generation. + /* + * Special comment for documentation generation. * All subclasses of `AstNode` that represent concrete syntax should have - * a comment of the form: */ - /* syntax: ... */ + * a comment of the form: + */ + /* syntax: ... */ /** Gets the scope that this node occurs in */ abstract Scope getScope(); - /** Gets a flow node corresponding directly to this node. + /** + * Gets a flow node corresponding directly to this node. * NOTE: For some statements and other purely syntactic elements, - * there may not be a `ControlFlowNode` */ - ControlFlowNode getAFlowNode() { - py_flow_bb_node(result, this, _, _) - } + * there may not be a `ControlFlowNode` + */ + ControlFlowNode getAFlowNode() { py_flow_bb_node(result, this, _, _) } /** Gets the location for this AST node */ - Location getLocation() { - none() - } + Location getLocation() { none() } - /** Whether this syntactic element is artificial, that is it is generated - * by the compiler and is not present in the source */ - predicate isArtificial() { - none() - } + /** + * Whether this syntactic element is artificial, that is it is generated + * by the compiler and is not present in the source + */ + predicate isArtificial() { none() } - /** Gets a child node of this node in the AST. This predicate exists to aid exploration of the AST - * and other experiments. The child-parent relation may not be meaningful. - * For a more meaningful relation in terms of dependency use - * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or - * Scope.getAStmt(). - */ + /** + * Gets a child node of this node in the AST. This predicate exists to aid exploration of the AST + * and other experiments. The child-parent relation may not be meaningful. + * For a more meaningful relation in terms of dependency use + * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or + * Scope.getAStmt(). + */ abstract AstNode getAChildNode(); - /** Gets the parent node of this node in the AST. This predicate exists to aid exploration of the AST - * and other experiments. The child-parent relation may not be meaningful. - * For a more meaningful relation in terms of dependency use - * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or - * Scope.getAStmt() applied to the parent. - */ - AstNode getParentNode() { - result.getAChildNode() = this - } + /** + * Gets the parent node of this node in the AST. This predicate exists to aid exploration of the AST + * and other experiments. The child-parent relation may not be meaningful. + * For a more meaningful relation in terms of dependency use + * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or + * Scope.getAStmt() applied to the parent. + */ + AstNode getParentNode() { result.getAChildNode() = this } /** Whether this contains `inner` syntactically */ - predicate contains(AstNode inner) { - this.getAChildNode+() = inner - } + predicate contains(AstNode inner) { this.getAChildNode+() = inner } /** Whether this contains `inner` syntactically and `inner` has the same scope as `this` */ predicate containsInScope(AstNode inner) { @@ -58,133 +55,86 @@ abstract class AstNode extends AstNode_ { this.getScope() = inner.getScope() and not inner instanceof Scope } - } /* Parents */ +/** Internal implementation class */ +library class FunctionParent extends FunctionParent_ { } /** Internal implementation class */ -library class FunctionParent extends FunctionParent_ { - -} +library class ArgumentsParent extends ArgumentsParent_ { } /** Internal implementation class */ -library class ArgumentsParent extends ArgumentsParent_ { - -} +library class ExprListParent extends ExprListParent_ { } /** Internal implementation class */ -library class ExprListParent extends ExprListParent_ { - -} +library class ExprContextParent extends ExprContextParent_ { } /** Internal implementation class */ -library class ExprContextParent extends ExprContextParent_ { - -} +library class StmtListParent extends StmtListParent_ { } /** Internal implementation class */ -library class StmtListParent extends StmtListParent_ { - -} +library class StrListParent extends StrListParent_ { } /** Internal implementation class */ -library class StrListParent extends StrListParent_ { - -} - -/** Internal implementation class */ -library class ExprParent extends ExprParent_ { - -} +library class ExprParent extends ExprParent_ { } library class DictItem extends DictItem_, AstNode { - - override string toString() { - result = DictItem_.super.toString() - } + override string toString() { result = DictItem_.super.toString() } override AstNode getAChildNode() { none() } override Scope getScope() { none() } - } /** A comprehension part, the 'for a in seq' part of [ a * a for a in seq ] */ class Comprehension extends Comprehension_, AstNode { - /** Gets the scope of this comprehension */ override Scope getScope() { /* Comprehensions exists only in Python 2 list comprehensions, so their scope is that of the list comp. */ - exists(ListComp l | - this = l.getAGenerator() | - result = l.getScope() - ) + exists(ListComp l | this = l.getAGenerator() | result = l.getScope()) } - override string toString() { - result = "Comprehension" - } + override string toString() { result = "Comprehension" } - override Location getLocation() { - result = Comprehension_.super.getLocation() - } + override Location getLocation() { result = Comprehension_.super.getLocation() } - override AstNode getAChildNode() { - result = this.getASubExpression() - } + override AstNode getAChildNode() { result = this.getASubExpression() } Expr getASubExpression() { result = this.getIter() or result = this.getAnIf() or result = this.getTarget() } - } -class BytesOrStr extends BytesOrStr_ { +class BytesOrStr extends BytesOrStr_ { } -} - -/** Part of a string literal formed by implicit concatenation. +/** + * Part of a string literal formed by implicit concatenation. * For example the string literal "abc" expressed in the source as `"a" "b" "c"` * would be composed of three `StringPart`s. - * */ class StringPart extends StringPart_, AstNode { - override Scope getScope() { exists(Bytes b | this = b.getAnImplicitlyConcatenatedPart() | result = b.getScope()) or exists(Unicode u | this = u.getAnImplicitlyConcatenatedPart() | result = u.getScope()) } - override AstNode getAChildNode() { - none() - } + override AstNode getAChildNode() { none() } - override string toString() { - result = StringPart_.super.toString() - } - - override Location getLocation() { - result = StringPart_.super.getLocation() - } + override string toString() { result = StringPart_.super.toString() } + override Location getLocation() { result = StringPart_.super.getLocation() } } -class StringPartList extends StringPartList_ { - -} +class StringPartList extends StringPartList_ { } /* **** Lists ***/ - /** A parameter list */ class ParameterList extends @py_parameter_list { - - Function getParent() { - py_parameter_lists(this, result) - } + Function getParent() { py_parameter_lists(this, result) } /** Gets a parameter */ Parameter getAnItem() { @@ -198,40 +148,23 @@ class ParameterList extends @py_parameter_list { py_exprs(result, _, this, index) } - string toString() { - result = "ParameterList" - } + string toString() { result = "ParameterList" } } /** A list of Comprehensions (for generating parts of a set, list or dictionary comprehension) */ -class ComprehensionList extends ComprehensionList_ { - -} +class ComprehensionList extends ComprehensionList_ { } /** A list of expressions */ class ExprList extends ExprList_ { - /* syntax: Expr, ... */ - } +library class DictItemList extends DictItemList_ { } -library class DictItemList extends DictItemList_ { - -} - -library class DictItemListParent extends DictItemListParent_ { - -} +library class DictItemListParent extends DictItemListParent_ { } /** A list of strings (the primitive type string not Bytes or Unicode) */ -class StringList extends StringList_ { - -} +class StringList extends StringList_ { } /** A list of aliases in an import statement */ -class AliasList extends AliasList_ { - -} - - +class AliasList extends AliasList_ { } diff --git a/python/ql/src/semmle/python/AstGenerated.qll b/python/ql/src/semmle/python/AstGenerated.qll index 6832b3f2da6..13e803650cc 100644 --- a/python/ql/src/semmle/python/AstGenerated.qll +++ b/python/ql/src/semmle/python/AstGenerated.qll @@ -3,304 +3,157 @@ * WARNING: Any modifications to this file will be lost. * Relations can be changed by modifying master.py. */ + import python library class Add_ extends @py_Add, Operator { - - override string toString() { - result = "Add" - } - + override string toString() { result = "Add" } } library class And_ extends @py_And, Boolop { - - override string toString() { - result = "And" - } - + override string toString() { result = "And" } } library class AnnAssign_ extends @py_AnnAssign, Stmt { - - /** Gets the value of this annotated assignment. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the annotation of this annotated assignment. */ - Expr getAnnotation() { - py_exprs(result, _, this, 2) - } - + Expr getAnnotation() { py_exprs(result, _, this, 2) } /** Gets the target of this annotated assignment. */ - Expr getTarget() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "AnnAssign" - } + Expr getTarget() { py_exprs(result, _, this, 3) } + override string toString() { result = "AnnAssign" } } library class Assert_ extends @py_Assert, Stmt { - - /** Gets the value being tested of this assert statement. */ - Expr getTest() { - py_exprs(result, _, this, 1) - } - + Expr getTest() { py_exprs(result, _, this, 1) } /** Gets the failure message of this assert statement. */ - Expr getMsg() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Assert" - } + Expr getMsg() { py_exprs(result, _, this, 2) } + override string toString() { result = "Assert" } } library class Assign_ extends @py_Assign, Stmt { - - /** Gets the value of this assignment statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the targets of this assignment statement. */ - ExprList getTargets() { - py_expr_lists(result, this, 2) - } - + ExprList getTargets() { py_expr_lists(result, this, 2) } /** Gets the nth target of this assignment statement. */ - Expr getTarget(int index) { - result = this.getTargets().getItem(index) - } + Expr getTarget(int index) { result = this.getTargets().getItem(index) } /** Gets a target of this assignment statement. */ - Expr getATarget() { - result = this.getTargets().getAnItem() - } - - override string toString() { - result = "Assign" - } + Expr getATarget() { result = this.getTargets().getAnItem() } + override string toString() { result = "Assign" } } library class AssignExpr_ extends @py_AssignExpr, Expr { - - /** Gets the value of this assignment expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the target of this assignment expression. */ - Expr getTarget() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "AssignExpr" - } + Expr getTarget() { py_exprs(result, _, this, 3) } + override string toString() { result = "AssignExpr" } } library class Attribute_ extends @py_Attribute, Expr { - - /** Gets the object of this attribute expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the attribute name of this attribute expression. */ - string getAttr() { - py_strs(result, this, 3) - } - + string getAttr() { py_strs(result, this, 3) } /** Gets the context of this attribute expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "Attribute" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "Attribute" } } library class AugAssign_ extends @py_AugAssign, Stmt { - - /** Gets the operation of this augmented assignment statement. */ - BinaryExpr getOperation() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "AugAssign" - } + BinaryExpr getOperation() { py_exprs(result, _, this, 1) } + override string toString() { result = "AugAssign" } } library class AugLoad_ extends @py_AugLoad, ExprContext { - - override string toString() { - result = "AugLoad" - } - + override string toString() { result = "AugLoad" } } library class AugStore_ extends @py_AugStore, ExprContext { - - override string toString() { - result = "AugStore" - } - + override string toString() { result = "AugStore" } } library class Await_ extends @py_Await, Expr { - - /** Gets the expression waited upon of this await expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Await" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "Await" } } library class BinaryExpr_ extends @py_BinaryExpr, Expr { - - /** Gets the left sub-expression of this binary expression. */ - Expr getLeft() { - py_exprs(result, _, this, 2) - } - + Expr getLeft() { py_exprs(result, _, this, 2) } /** Gets the operator of this binary expression. */ - Operator getOp() { - py_operators(result, _, this) - } - + Operator getOp() { py_operators(result, _, this) } /** Gets the right sub-expression of this binary expression. */ - Expr getRight() { - py_exprs(result, _, this, 4) - } + Expr getRight() { py_exprs(result, _, this, 4) } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "BinaryExpr" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "BinaryExpr" } } library class BitAnd_ extends @py_BitAnd, Operator { - - override string toString() { - result = "BitAnd" - } - + override string toString() { result = "BitAnd" } } library class BitOr_ extends @py_BitOr, Operator { - - override string toString() { - result = "BitOr" - } - + override string toString() { result = "BitOr" } } library class BitXor_ extends @py_BitXor, Operator { - - override string toString() { - result = "BitXor" - } - + override string toString() { result = "BitXor" } } library class BoolExpr_ extends @py_BoolExpr, Expr { - - /** Gets the operator of this boolean expression. */ - Boolop getOp() { - py_boolops(result, _, this) - } - + Boolop getOp() { py_boolops(result, _, this) } /** Gets the sub-expressions of this boolean expression. */ - ExprList getValues() { - py_expr_lists(result, this, 3) - } - + ExprList getValues() { py_expr_lists(result, this, 3) } /** Gets the nth sub-expression of this boolean expression. */ - Expr getValue(int index) { - result = this.getValues().getItem(index) - } + Expr getValue(int index) { result = this.getValues().getItem(index) } /** Gets a sub-expression of this boolean expression. */ - Expr getAValue() { - result = this.getValues().getAnItem() - } - - override string toString() { - result = "BoolExpr" - } + Expr getAValue() { result = this.getValues().getAnItem() } + override string toString() { result = "BoolExpr" } } library class Break_ extends @py_Break, Stmt { - - override string toString() { - result = "Break" - } - + override string toString() { result = "Break" } } library class Bytes_ extends @py_Bytes, Expr { - - /** Gets the value of this bytes expression. */ - string getS() { - py_bytes(result, this, 2) - } - + string getS() { py_bytes(result, this, 2) } /** Gets the prefix of this bytes expression. */ - string getPrefix() { - py_bytes(result, this, 3) - } - + string getPrefix() { py_bytes(result, this, 3) } /** Gets the implicitly_concatenated_parts of this bytes expression. */ - StringPartList getImplicitlyConcatenatedParts() { - py_StringPart_lists(result, this) - } - + StringPartList getImplicitlyConcatenatedParts() { py_StringPart_lists(result, this) } /** Gets the nth implicitly_concatenated_part of this bytes expression. */ StringPart getImplicitlyConcatenatedPart(int index) { @@ -312,1559 +165,795 @@ library class Bytes_ extends @py_Bytes, Expr { result = this.getImplicitlyConcatenatedParts().getAnItem() } - override string toString() { - result = "Bytes" - } - + override string toString() { result = "Bytes" } } library class BytesOrStr_ extends @py_Bytes_or_Str { - - string toString() { - result = "BytesOrStr" - } - + string toString() { result = "BytesOrStr" } } library class Call_ extends @py_Call, Expr { - - /** Gets the callable of this call expression. */ - Expr getFunc() { - py_exprs(result, _, this, 2) - } - + Expr getFunc() { py_exprs(result, _, this, 2) } /** Gets the positional arguments of this call expression. */ - ExprList getPositionalArgs() { - py_expr_lists(result, this, 3) - } - + ExprList getPositionalArgs() { py_expr_lists(result, this, 3) } /** Gets the nth positional argument of this call expression. */ - Expr getPositionalArg(int index) { - result = this.getPositionalArgs().getItem(index) - } + Expr getPositionalArg(int index) { result = this.getPositionalArgs().getItem(index) } /** Gets a positional argument of this call expression. */ - Expr getAPositionalArg() { - result = this.getPositionalArgs().getAnItem() - } - + Expr getAPositionalArg() { result = this.getPositionalArgs().getAnItem() } /** Gets the named arguments of this call expression. */ - DictItemList getNamedArgs() { - py_dict_item_lists(result, this) - } - + DictItemList getNamedArgs() { py_dict_item_lists(result, this) } /** Gets the nth named argument of this call expression. */ - DictItem getNamedArg(int index) { - result = this.getNamedArgs().getItem(index) - } + DictItem getNamedArg(int index) { result = this.getNamedArgs().getItem(index) } /** Gets a named argument of this call expression. */ - DictItem getANamedArg() { - result = this.getNamedArgs().getAnItem() - } - - override string toString() { - result = "Call" - } + DictItem getANamedArg() { result = this.getNamedArgs().getAnItem() } + override string toString() { result = "Call" } } library class Class_ extends @py_Class { - - /** Gets the name of this class. */ - string getName() { - py_strs(result, this, 0) - } - + string getName() { py_strs(result, this, 0) } /** Gets the body of this class. */ - StmtList getBody() { - py_stmt_lists(result, this, 1) - } - + StmtList getBody() { py_stmt_lists(result, this, 1) } /** Gets the nth statement of this class. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this class. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } + Stmt getAStmt() { result = this.getBody().getAnItem() } - ClassExpr getParent() { - py_Classes(this, result) - } - - string toString() { - result = "Class" - } + ClassExpr getParent() { py_Classes(this, result) } + string toString() { result = "Class" } } library class ClassExpr_ extends @py_ClassExpr, Expr { - - /** Gets the name of this class definition. */ - string getName() { - py_strs(result, this, 2) - } - + string getName() { py_strs(result, this, 2) } /** Gets the bases of this class definition. */ - ExprList getBases() { - py_expr_lists(result, this, 3) - } - + ExprList getBases() { py_expr_lists(result, this, 3) } /** Gets the nth base of this class definition. */ - Expr getBase(int index) { - result = this.getBases().getItem(index) - } + Expr getBase(int index) { result = this.getBases().getItem(index) } /** Gets a base of this class definition. */ - Expr getABase() { - result = this.getBases().getAnItem() - } - + Expr getABase() { result = this.getBases().getAnItem() } /** Gets the keyword arguments of this class definition. */ - DictItemList getKeywords() { - py_dict_item_lists(result, this) - } - + DictItemList getKeywords() { py_dict_item_lists(result, this) } /** Gets the nth keyword argument of this class definition. */ - DictItem getKeyword(int index) { - result = this.getKeywords().getItem(index) - } + DictItem getKeyword(int index) { result = this.getKeywords().getItem(index) } /** Gets a keyword argument of this class definition. */ - DictItem getAKeyword() { - result = this.getKeywords().getAnItem() - } - + DictItem getAKeyword() { result = this.getKeywords().getAnItem() } /** Gets the class scope of this class definition. */ - Class getInnerScope() { - py_Classes(result, this) - } - - override string toString() { - result = "ClassExpr" - } + Class getInnerScope() { py_Classes(result, this) } + override string toString() { result = "ClassExpr" } } library class Compare_ extends @py_Compare, Expr { - - /** Gets the left sub-expression of this compare expression. */ - Expr getLeft() { - py_exprs(result, _, this, 2) - } - + Expr getLeft() { py_exprs(result, _, this, 2) } /** Gets the comparison operators of this compare expression. */ - CmpopList getOps() { - py_cmpop_lists(result, this) - } - + CmpopList getOps() { py_cmpop_lists(result, this) } /** Gets the nth comparison operator of this compare expression. */ - Cmpop getOp(int index) { - result = this.getOps().getItem(index) - } + Cmpop getOp(int index) { result = this.getOps().getItem(index) } /** Gets a comparison operator of this compare expression. */ - Cmpop getAnOp() { - result = this.getOps().getAnItem() - } - + Cmpop getAnOp() { result = this.getOps().getAnItem() } /** Gets the right sub-expressions of this compare expression. */ - ExprList getComparators() { - py_expr_lists(result, this, 4) - } - + ExprList getComparators() { py_expr_lists(result, this, 4) } /** Gets the nth right sub-expression of this compare expression. */ - Expr getComparator(int index) { - result = this.getComparators().getItem(index) - } + Expr getComparator(int index) { result = this.getComparators().getItem(index) } /** Gets a right sub-expression of this compare expression. */ - Expr getAComparator() { - result = this.getComparators().getAnItem() - } - - override string toString() { - result = "Compare" - } + Expr getAComparator() { result = this.getComparators().getAnItem() } + override string toString() { result = "Compare" } } library class Continue_ extends @py_Continue, Stmt { - - override string toString() { - result = "Continue" - } - + override string toString() { result = "Continue" } } library class Del_ extends @py_Del, ExprContext { - - override string toString() { - result = "Del" - } - + override string toString() { result = "Del" } } library class Delete_ extends @py_Delete, Stmt { - - /** Gets the targets of this delete statement. */ - ExprList getTargets() { - py_expr_lists(result, this, 1) - } - + ExprList getTargets() { py_expr_lists(result, this, 1) } /** Gets the nth target of this delete statement. */ - Expr getTarget(int index) { - result = this.getTargets().getItem(index) - } + Expr getTarget(int index) { result = this.getTargets().getItem(index) } /** Gets a target of this delete statement. */ - Expr getATarget() { - result = this.getTargets().getAnItem() - } - - override string toString() { - result = "Delete" - } + Expr getATarget() { result = this.getTargets().getAnItem() } + override string toString() { result = "Delete" } } library class Dict_ extends @py_Dict, Expr { - - /** Gets the items of this dictionary expression. */ - DictItemList getItems() { - py_dict_item_lists(result, this) - } - + DictItemList getItems() { py_dict_item_lists(result, this) } /** Gets the nth item of this dictionary expression. */ - DictItem getItem(int index) { - result = this.getItems().getItem(index) - } + DictItem getItem(int index) { result = this.getItems().getItem(index) } /** Gets an item of this dictionary expression. */ - DictItem getAnItem() { - result = this.getItems().getAnItem() - } - - override string toString() { - result = "Dict" - } + DictItem getAnItem() { result = this.getItems().getAnItem() } + override string toString() { result = "Dict" } } library class DictComp_ extends @py_DictComp, Expr { - - /** Gets the implementation of this dictionary comprehension. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this dictionary comprehension. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "DictComp" - } + Expr getIterable() { py_exprs(result, _, this, 3) } + override string toString() { result = "DictComp" } } library class DictUnpacking_ extends @py_DictUnpacking, DictItem { - - /** Gets the location of this dictionary unpacking. */ - override Location getLocation() { - py_locations(result, this) - } - + override Location getLocation() { py_locations(result, this) } /** Gets the value of this dictionary unpacking. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "DictUnpacking" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "DictUnpacking" } } library class Div_ extends @py_Div, Operator { - - override string toString() { - result = "Div" - } - + override string toString() { result = "Div" } } library class Ellipsis_ extends @py_Ellipsis, Expr { - - override string toString() { - result = "Ellipsis" - } - + override string toString() { result = "Ellipsis" } } library class Eq_ extends @py_Eq, Cmpop { - - override string toString() { - result = "Eq" - } - + override string toString() { result = "Eq" } } library class ExceptStmt_ extends @py_ExceptStmt, Stmt { - - /** Gets the type of this except block. */ - Expr getType() { - py_exprs(result, _, this, 1) - } - + Expr getType() { py_exprs(result, _, this, 1) } /** Gets the name of this except block. */ - Expr getName() { - py_exprs(result, _, this, 2) - } - + Expr getName() { py_exprs(result, _, this, 2) } /** Gets the body of this except block. */ - StmtList getBody() { - py_stmt_lists(result, this, 3) - } - + StmtList getBody() { py_stmt_lists(result, this, 3) } /** Gets the nth statement of this except block. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this except block. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - - override string toString() { - result = "ExceptStmt" - } + Stmt getAStmt() { result = this.getBody().getAnItem() } + override string toString() { result = "ExceptStmt" } } library class Exec_ extends @py_Exec, Stmt { - - /** Gets the body of this exec statement. */ - Expr getBody() { - py_exprs(result, _, this, 1) - } - + Expr getBody() { py_exprs(result, _, this, 1) } /** Gets the globals of this exec statement. */ - Expr getGlobals() { - py_exprs(result, _, this, 2) - } - + Expr getGlobals() { py_exprs(result, _, this, 2) } /** Gets the locals of this exec statement. */ - Expr getLocals() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "Exec" - } + Expr getLocals() { py_exprs(result, _, this, 3) } + override string toString() { result = "Exec" } } library class ExprStmt_ extends @py_Expr_stmt, Stmt { - - /** Gets the value of this expr statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "ExprStmt" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "ExprStmt" } } library class Filter_ extends @py_Filter, Expr { - - /** Gets the filtered value of this template filter expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the filter of this template filter expression. */ - Expr getFilter() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "Filter" - } + Expr getFilter() { py_exprs(result, _, this, 3) } + override string toString() { result = "Filter" } } library class FloorDiv_ extends @py_FloorDiv, Operator { - - override string toString() { - result = "FloorDiv" - } - + override string toString() { result = "FloorDiv" } } library class For_ extends @py_For, Stmt { - - /** Gets the target of this for statement. */ - Expr getTarget() { - py_exprs(result, _, this, 1) - } - + Expr getTarget() { py_exprs(result, _, this, 1) } /** Gets the iterable of this for statement. */ - Expr getIter() { - py_exprs(result, _, this, 2) - } - + Expr getIter() { py_exprs(result, _, this, 2) } /** Gets the body of this for statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 3) - } - + StmtList getBody() { py_stmt_lists(result, this, 3) } /** Gets the nth statement of this for statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this for statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the else block of this for statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 4) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 4) } /** Gets the nth else statement of this for statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an else statement of this for statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } /** Whether the async property of this for statement is true. */ - predicate isAsync() { - py_bools(this, 5) - } - - override string toString() { - result = "For" - } + predicate isAsync() { py_bools(this, 5) } + override string toString() { result = "For" } } library class FormattedValue_ extends @py_FormattedValue, Expr { - - /** Gets the expression to be formatted of this formatted value. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the type conversion of this formatted value. */ - string getConversion() { - py_strs(result, this, 3) - } - + string getConversion() { py_strs(result, this, 3) } /** Gets the format specifier of this formatted value. */ - Fstring getFormatSpec() { - py_exprs(result, _, this, 4) - } - - override string toString() { - result = "FormattedValue" - } + Fstring getFormatSpec() { py_exprs(result, _, this, 4) } + override string toString() { result = "FormattedValue" } } library class Function_ extends @py_Function { - - /** Gets the name of this function. */ - string getName() { - py_strs(result, this, 0) - } - + string getName() { py_strs(result, this, 0) } /** Gets the positional parameter list of this function. */ - ParameterList getArgs() { - py_parameter_lists(result, this) - } - + ParameterList getArgs() { py_parameter_lists(result, this) } /** Gets the nth positional parameter of this function. */ - Parameter getArg(int index) { - result = this.getArgs().getItem(index) - } + Parameter getArg(int index) { result = this.getArgs().getItem(index) } /** Gets a positional parameter of this function. */ - Parameter getAnArg() { - result = this.getArgs().getAnItem() - } - + Parameter getAnArg() { result = this.getArgs().getAnItem() } /** Gets the tuple (*) parameter of this function. */ - Expr getVararg() { - py_exprs(result, _, this, 2) - } - + Expr getVararg() { py_exprs(result, _, this, 2) } /** Gets the keyword-only parameter list of this function. */ - ExprList getKwonlyargs() { - py_expr_lists(result, this, 3) - } - + ExprList getKwonlyargs() { py_expr_lists(result, this, 3) } /** Gets the nth keyword-only parameter of this function. */ - Expr getKwonlyarg(int index) { - result = this.getKwonlyargs().getItem(index) - } + Expr getKwonlyarg(int index) { result = this.getKwonlyargs().getItem(index) } /** Gets a keyword-only parameter of this function. */ - Expr getAKwonlyarg() { - result = this.getKwonlyargs().getAnItem() - } - + Expr getAKwonlyarg() { result = this.getKwonlyargs().getAnItem() } /** Gets the dictionary (**) parameter of this function. */ - Expr getKwarg() { - py_exprs(result, _, this, 4) - } - + Expr getKwarg() { py_exprs(result, _, this, 4) } /** Gets the body of this function. */ - StmtList getBody() { - py_stmt_lists(result, this, 5) - } - + StmtList getBody() { py_stmt_lists(result, this, 5) } /** Gets the nth statement of this function. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this function. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Whether the async property of this function is true. */ - predicate isAsync() { - py_bools(this, 6) - } + predicate isAsync() { py_bools(this, 6) } - FunctionParent getParent() { - py_Functions(this, result) - } - - string toString() { - result = "Function" - } + FunctionParent getParent() { py_Functions(this, result) } + string toString() { result = "Function" } } library class FunctionExpr_ extends @py_FunctionExpr, Expr { - - /** Gets the name of this function definition. */ - string getName() { - py_strs(result, this, 2) - } - + string getName() { py_strs(result, this, 2) } /** Gets the parameters of this function definition. */ - Arguments getArgs() { - py_arguments(result, this) - } - + Arguments getArgs() { py_arguments(result, this) } /** Gets the return annotation of this function definition. */ - Expr getReturns() { - py_exprs(result, _, this, 4) - } - + Expr getReturns() { py_exprs(result, _, this, 4) } /** Gets the function scope of this function definition. */ - Function getInnerScope() { - py_Functions(result, this) - } - - override string toString() { - result = "FunctionExpr" - } + Function getInnerScope() { py_Functions(result, this) } + override string toString() { result = "FunctionExpr" } } library class FunctionParent_ extends @py_Function_parent { - - string toString() { - result = "FunctionParent" - } - + string toString() { result = "FunctionParent" } } library class GeneratorExp_ extends @py_GeneratorExp, Expr { - - /** Gets the implementation of this generator expression. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this generator expression. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "GeneratorExp" - } + Expr getIterable() { py_exprs(result, _, this, 3) } + override string toString() { result = "GeneratorExp" } } library class Global_ extends @py_Global, Stmt { - - /** Gets the names of this global statement. */ - StringList getNames() { - py_str_lists(result, this) - } - + StringList getNames() { py_str_lists(result, this) } /** Gets the nth name of this global statement. */ - string getName(int index) { - result = this.getNames().getItem(index) - } + string getName(int index) { result = this.getNames().getItem(index) } /** Gets a name of this global statement. */ - string getAName() { - result = this.getNames().getAnItem() - } - - override string toString() { - result = "Global" - } + string getAName() { result = this.getNames().getAnItem() } + override string toString() { result = "Global" } } library class Gt_ extends @py_Gt, Cmpop { - - override string toString() { - result = "Gt" - } - + override string toString() { result = "Gt" } } library class GtE_ extends @py_GtE, Cmpop { - - override string toString() { - result = "GtE" - } - + override string toString() { result = "GtE" } } library class If_ extends @py_If, Stmt { - - /** Gets the test of this if statement. */ - Expr getTest() { - py_exprs(result, _, this, 1) - } - + Expr getTest() { py_exprs(result, _, this, 1) } /** Gets the if-true block of this if statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 2) - } - + StmtList getBody() { py_stmt_lists(result, this, 2) } /** Gets the nth if-true statement of this if statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets an if-true statement of this if statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the if-false block of this if statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 3) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 3) } /** Gets the nth if-false statement of this if statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an if-false statement of this if statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - - override string toString() { - result = "If" - } + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } + override string toString() { result = "If" } } library class IfExp_ extends @py_IfExp, Expr { - - /** Gets the test of this if expression. */ - Expr getTest() { - py_exprs(result, _, this, 2) - } - + Expr getTest() { py_exprs(result, _, this, 2) } /** Gets the if-true expression of this if expression. */ - Expr getBody() { - py_exprs(result, _, this, 3) - } - + Expr getBody() { py_exprs(result, _, this, 3) } /** Gets the if-false expression of this if expression. */ - Expr getOrelse() { - py_exprs(result, _, this, 4) - } - - override string toString() { - result = "IfExp" - } + Expr getOrelse() { py_exprs(result, _, this, 4) } + override string toString() { result = "IfExp" } } library class Import_ extends @py_Import, Stmt { - - /** Gets the alias list of this import statement. */ - AliasList getNames() { - py_alias_lists(result, this) - } - + AliasList getNames() { py_alias_lists(result, this) } /** Gets the nth alias of this import statement. */ - Alias getName(int index) { - result = this.getNames().getItem(index) - } + Alias getName(int index) { result = this.getNames().getItem(index) } /** Gets an alias of this import statement. */ - Alias getAName() { - result = this.getNames().getAnItem() - } - - override string toString() { - result = "Import" - } + Alias getAName() { result = this.getNames().getAnItem() } + override string toString() { result = "Import" } } library class ImportExpr_ extends @py_ImportExpr, Expr { - - /** Gets the level of this import expression. */ - int getLevel() { - py_ints(result, this) - } - + int getLevel() { py_ints(result, this) } /** Gets the name of this import expression. */ - string getName() { - py_strs(result, this, 3) - } - + string getName() { py_strs(result, this, 3) } /** Whether the top level property of this import expression is true. */ - predicate isTop() { - py_bools(this, 4) - } - - override string toString() { - result = "ImportExpr" - } + predicate isTop() { py_bools(this, 4) } + override string toString() { result = "ImportExpr" } } library class ImportStar_ extends @py_ImportStar, Stmt { - - /** Gets the module of this import * statement. */ - Expr getModule() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "ImportStar" - } + Expr getModule() { py_exprs(result, _, this, 1) } + override string toString() { result = "ImportStar" } } library class ImportMember_ extends @py_ImportMember, Expr { - - /** Gets the module of this from import. */ - Expr getModule() { - py_exprs(result, _, this, 2) - } - + Expr getModule() { py_exprs(result, _, this, 2) } /** Gets the name of this from import. */ - string getName() { - py_strs(result, this, 3) - } - - override string toString() { - result = "ImportMember" - } + string getName() { py_strs(result, this, 3) } + override string toString() { result = "ImportMember" } } library class In_ extends @py_In, Cmpop { - - override string toString() { - result = "In" - } - + override string toString() { result = "In" } } library class Invert_ extends @py_Invert, Unaryop { - - override string toString() { - result = "Invert" - } - + override string toString() { result = "Invert" } } library class Is_ extends @py_Is, Cmpop { - - override string toString() { - result = "Is" - } - + override string toString() { result = "Is" } } library class IsNot_ extends @py_IsNot, Cmpop { - - override string toString() { - result = "IsNot" - } - + override string toString() { result = "IsNot" } } library class Fstring_ extends @py_Fstring, Expr { - - /** Gets the values of this formatted string literal. */ - ExprList getValues() { - py_expr_lists(result, this, 2) - } - + ExprList getValues() { py_expr_lists(result, this, 2) } /** Gets the nth value of this formatted string literal. */ - Expr getValue(int index) { - result = this.getValues().getItem(index) - } + Expr getValue(int index) { result = this.getValues().getItem(index) } /** Gets a value of this formatted string literal. */ - Expr getAValue() { - result = this.getValues().getAnItem() - } + Expr getAValue() { result = this.getValues().getAnItem() } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "Fstring" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "Fstring" } } library class KeyValuePair_ extends @py_KeyValuePair, DictItem { - - /** Gets the location of this key-value pair. */ - override Location getLocation() { - py_locations(result, this) - } - + override Location getLocation() { py_locations(result, this) } /** Gets the value of this key-value pair. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the key of this key-value pair. */ - Expr getKey() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "KeyValuePair" - } + Expr getKey() { py_exprs(result, _, this, 2) } + override string toString() { result = "KeyValuePair" } } library class LShift_ extends @py_LShift, Operator { - - override string toString() { - result = "LShift" - } - + override string toString() { result = "LShift" } } library class Lambda_ extends @py_Lambda, Expr { - - /** Gets the arguments of this lambda expression. */ - Arguments getArgs() { - py_arguments(result, this) - } - + Arguments getArgs() { py_arguments(result, this) } /** Gets the function scope of this lambda expression. */ - Function getInnerScope() { - py_Functions(result, this) - } - - override string toString() { - result = "Lambda" - } + Function getInnerScope() { py_Functions(result, this) } + override string toString() { result = "Lambda" } } library class List_ extends @py_List, Expr { - - /** Gets the element list of this list expression. */ - ExprList getElts() { - py_expr_lists(result, this, 2) - } - + ExprList getElts() { py_expr_lists(result, this, 2) } /** Gets the nth element of this list expression. */ - Expr getElt(int index) { - result = this.getElts().getItem(index) - } + Expr getElt(int index) { result = this.getElts().getItem(index) } /** Gets an element of this list expression. */ - Expr getAnElt() { - result = this.getElts().getAnItem() - } - + Expr getAnElt() { result = this.getElts().getAnItem() } /** Gets the context of this list expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "List" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "List" } } library class ListComp_ extends @py_ListComp, Expr { - - /** Gets the implementation of this list comprehension. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this list comprehension. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - + Expr getIterable() { py_exprs(result, _, this, 3) } /** Gets the generators of this list comprehension. */ - ComprehensionList getGenerators() { - py_comprehension_lists(result, this) - } - + ComprehensionList getGenerators() { py_comprehension_lists(result, this) } /** Gets the nth generator of this list comprehension. */ - Comprehension getGenerator(int index) { - result = this.getGenerators().getItem(index) - } + Comprehension getGenerator(int index) { result = this.getGenerators().getItem(index) } /** Gets a generator of this list comprehension. */ - Comprehension getAGenerator() { - result = this.getGenerators().getAnItem() - } - + Comprehension getAGenerator() { result = this.getGenerators().getAnItem() } /** Gets the elements of this list comprehension. */ - Expr getElt() { - py_exprs(result, _, this, 5) - } - - override string toString() { - result = "ListComp" - } + Expr getElt() { py_exprs(result, _, this, 5) } + override string toString() { result = "ListComp" } } library class Load_ extends @py_Load, ExprContext { - - override string toString() { - result = "Load" - } - + override string toString() { result = "Load" } } library class Lt_ extends @py_Lt, Cmpop { - - override string toString() { - result = "Lt" - } - + override string toString() { result = "Lt" } } library class LtE_ extends @py_LtE, Cmpop { - - override string toString() { - result = "LtE" - } - + override string toString() { result = "LtE" } } library class MatMult_ extends @py_MatMult, Operator { - - override string toString() { - result = "MatMult" - } - + override string toString() { result = "MatMult" } } library class Mod_ extends @py_Mod, Operator { - - override string toString() { - result = "Mod" - } - + override string toString() { result = "Mod" } } library class Module_ extends @py_Module { - - /** Gets the name of this module. */ - string getName() { - py_strs(result, this, 0) - } - + string getName() { py_strs(result, this, 0) } /** Gets the hash (not populated) of this module. */ - string getHash() { - py_strs(result, this, 1) - } - + string getHash() { py_strs(result, this, 1) } /** Gets the body of this module. */ - StmtList getBody() { - py_stmt_lists(result, this, 2) - } - + StmtList getBody() { py_stmt_lists(result, this, 2) } /** Gets the nth statement of this module. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this module. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the kind of this module. */ - string getKind() { - py_strs(result, this, 3) - } - - string toString() { - result = "Module" - } + string getKind() { py_strs(result, this, 3) } + string toString() { result = "Module" } } library class Mult_ extends @py_Mult, Operator { - - override string toString() { - result = "Mult" - } - + override string toString() { result = "Mult" } } library class Name_ extends @py_Name, Expr { - - /** Gets the variable of this name expression. */ - Variable getVariable() { - py_variables(result, this) - } - + Variable getVariable() { py_variables(result, this) } /** Gets the context of this name expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "Name" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "Name" } } library class Nonlocal_ extends @py_Nonlocal, Stmt { - - /** Gets the names of this nonlocal statement. */ - StringList getNames() { - py_str_lists(result, this) - } - + StringList getNames() { py_str_lists(result, this) } /** Gets the nth name of this nonlocal statement. */ - string getName(int index) { - result = this.getNames().getItem(index) - } + string getName(int index) { result = this.getNames().getItem(index) } /** Gets a name of this nonlocal statement. */ - string getAName() { - result = this.getNames().getAnItem() - } - - override string toString() { - result = "Nonlocal" - } + string getAName() { result = this.getNames().getAnItem() } + override string toString() { result = "Nonlocal" } } library class Not_ extends @py_Not, Unaryop { - - override string toString() { - result = "Not" - } - + override string toString() { result = "Not" } } library class NotEq_ extends @py_NotEq, Cmpop { - - override string toString() { - result = "NotEq" - } - + override string toString() { result = "NotEq" } } library class NotIn_ extends @py_NotIn, Cmpop { - - override string toString() { - result = "NotIn" - } - + override string toString() { result = "NotIn" } } library class Num_ extends @py_Num, Expr { - - /** Gets the value of this numeric literal. */ - string getN() { - py_numbers(result, this, 2) - } - + string getN() { py_numbers(result, this, 2) } /** Gets the text of this numeric literal. */ - string getText() { - py_numbers(result, this, 3) - } - - override string toString() { - result = "Num" - } + string getText() { py_numbers(result, this, 3) } + override string toString() { result = "Num" } } library class Or_ extends @py_Or, Boolop { - - override string toString() { - result = "Or" - } - + override string toString() { result = "Or" } } library class Param_ extends @py_Param, ExprContext { - - override string toString() { - result = "Param" - } - + override string toString() { result = "Param" } } library class Pass_ extends @py_Pass, Stmt { - - override string toString() { - result = "Pass" - } - + override string toString() { result = "Pass" } } library class PlaceHolder_ extends @py_PlaceHolder, Expr { - - /** Gets the variable of this template place-holder expression. */ - Variable getVariable() { - py_variables(result, this) - } - + Variable getVariable() { py_variables(result, this) } /** Gets the context of this template place-holder expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "PlaceHolder" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "PlaceHolder" } } library class Pow_ extends @py_Pow, Operator { - - override string toString() { - result = "Pow" - } - + override string toString() { result = "Pow" } } library class Print_ extends @py_Print, Stmt { - - /** Gets the destination of this print statement. */ - Expr getDest() { - py_exprs(result, _, this, 1) - } - + Expr getDest() { py_exprs(result, _, this, 1) } /** Gets the values of this print statement. */ - ExprList getValues() { - py_expr_lists(result, this, 2) - } - + ExprList getValues() { py_expr_lists(result, this, 2) } /** Gets the nth value of this print statement. */ - Expr getValue(int index) { - result = this.getValues().getItem(index) - } + Expr getValue(int index) { result = this.getValues().getItem(index) } /** Gets a value of this print statement. */ - Expr getAValue() { - result = this.getValues().getAnItem() - } - + Expr getAValue() { result = this.getValues().getAnItem() } /** Whether the new line property of this print statement is true. */ - predicate isNl() { - py_bools(this, 3) - } - - override string toString() { - result = "Print" - } + predicate isNl() { py_bools(this, 3) } + override string toString() { result = "Print" } } library class RShift_ extends @py_RShift, Operator { - - override string toString() { - result = "RShift" - } - + override string toString() { result = "RShift" } } library class Raise_ extends @py_Raise, Stmt { - - /** Gets the exception of this raise statement. */ - Expr getExc() { - py_exprs(result, _, this, 1) - } - + Expr getExc() { py_exprs(result, _, this, 1) } /** Gets the cause of this raise statement. */ - Expr getCause() { - py_exprs(result, _, this, 2) - } - + Expr getCause() { py_exprs(result, _, this, 2) } /** Gets the type of this raise statement. */ - Expr getType() { - py_exprs(result, _, this, 3) - } - + Expr getType() { py_exprs(result, _, this, 3) } /** Gets the instance of this raise statement. */ - Expr getInst() { - py_exprs(result, _, this, 4) - } - + Expr getInst() { py_exprs(result, _, this, 4) } /** Gets the traceback of this raise statement. */ - Expr getTback() { - py_exprs(result, _, this, 5) - } - - override string toString() { - result = "Raise" - } + Expr getTback() { py_exprs(result, _, this, 5) } + override string toString() { result = "Raise" } } library class Repr_ extends @py_Repr, Expr { - - /** Gets the value of this backtick expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Repr" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "Repr" } } library class Return_ extends @py_Return, Stmt { - - /** Gets the value of this return statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "Return" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "Return" } } library class Set_ extends @py_Set, Expr { - - /** Gets the elements of this set expression. */ - ExprList getElts() { - py_expr_lists(result, this, 2) - } - + ExprList getElts() { py_expr_lists(result, this, 2) } /** Gets the nth element of this set expression. */ - Expr getElt(int index) { - result = this.getElts().getItem(index) - } + Expr getElt(int index) { result = this.getElts().getItem(index) } /** Gets an element of this set expression. */ - Expr getAnElt() { - result = this.getElts().getAnItem() - } - - override string toString() { - result = "Set" - } + Expr getAnElt() { result = this.getElts().getAnItem() } + override string toString() { result = "Set" } } library class SetComp_ extends @py_SetComp, Expr { - - /** Gets the implementation of this set comprehension. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this set comprehension. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "SetComp" - } + Expr getIterable() { py_exprs(result, _, this, 3) } + override string toString() { result = "SetComp" } } library class Slice_ extends @py_Slice, Expr { - - /** Gets the start of this slice. */ - Expr getStart() { - py_exprs(result, _, this, 2) - } - + Expr getStart() { py_exprs(result, _, this, 2) } /** Gets the stop of this slice. */ - Expr getStop() { - py_exprs(result, _, this, 3) - } - + Expr getStop() { py_exprs(result, _, this, 3) } /** Gets the step of this slice. */ - Expr getStep() { - py_exprs(result, _, this, 4) - } - - override string toString() { - result = "Slice" - } + Expr getStep() { py_exprs(result, _, this, 4) } + override string toString() { result = "Slice" } } library class SpecialOperation_ extends @py_SpecialOperation, Expr { - - /** Gets the name of this special operation. */ - string getName() { - py_strs(result, this, 2) - } - + string getName() { py_strs(result, this, 2) } /** Gets the arguments of this special operation. */ - ExprList getArguments() { - py_expr_lists(result, this, 3) - } - + ExprList getArguments() { py_expr_lists(result, this, 3) } /** Gets the nth argument of this special operation. */ - Expr getArgument(int index) { - result = this.getArguments().getItem(index) - } + Expr getArgument(int index) { result = this.getArguments().getItem(index) } /** Gets an argument of this special operation. */ - Expr getAnArgument() { - result = this.getArguments().getAnItem() - } - - override string toString() { - result = "SpecialOperation" - } + Expr getAnArgument() { result = this.getArguments().getAnItem() } + override string toString() { result = "SpecialOperation" } } library class Starred_ extends @py_Starred, Expr { - - /** Gets the value of this starred expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the context of this starred expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "Starred" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "Starred" } } library class Store_ extends @py_Store, ExprContext { - - override string toString() { - result = "Store" - } - + override string toString() { result = "Store" } } library class Str_ extends @py_Str, Expr { - - /** Gets the text of this string literal. */ - string getS() { - py_strs(result, this, 2) - } - + string getS() { py_strs(result, this, 2) } /** Gets the prefix of this string literal. */ - string getPrefix() { - py_strs(result, this, 3) - } - + string getPrefix() { py_strs(result, this, 3) } /** Gets the implicitly_concatenated_parts of this string literal. */ - StringPartList getImplicitlyConcatenatedParts() { - py_StringPart_lists(result, this) - } - + StringPartList getImplicitlyConcatenatedParts() { py_StringPart_lists(result, this) } /** Gets the nth implicitly_concatenated_part of this string literal. */ StringPart getImplicitlyConcatenatedPart(int index) { @@ -1876,972 +965,501 @@ library class Str_ extends @py_Str, Expr { result = this.getImplicitlyConcatenatedParts().getAnItem() } - override string toString() { - result = "Str" - } - + override string toString() { result = "Str" } } library class StringPart_ extends @py_StringPart { - - /** Gets the text of this implicitly concatenated part. */ - string getText() { - py_strs(result, this, 0) - } - + string getText() { py_strs(result, this, 0) } /** Gets the location of this implicitly concatenated part. */ - Location getLocation() { - py_locations(result, this) - } + Location getLocation() { py_locations(result, this) } - StringPartList getParent() { - py_StringParts(this, result, _) - } - - string toString() { - result = "StringPart" - } + StringPartList getParent() { py_StringParts(this, result, _) } + string toString() { result = "StringPart" } } library class StringPartList_ extends @py_StringPart_list { - - BytesOrStr getParent() { - py_StringPart_lists(this, result) - } + BytesOrStr getParent() { py_StringPart_lists(this, result) } /** Gets an item of this implicitly concatenated part list */ - StringPart getAnItem() { - py_StringParts(result, this, _) - } + StringPart getAnItem() { py_StringParts(result, this, _) } /** Gets the nth item of this implicitly concatenated part list */ - StringPart getItem(int index) { - py_StringParts(result, this, index) - } - - string toString() { - result = "StringPartList" - } + StringPart getItem(int index) { py_StringParts(result, this, index) } + string toString() { result = "StringPartList" } } library class Sub_ extends @py_Sub, Operator { - - override string toString() { - result = "Sub" - } - + override string toString() { result = "Sub" } } library class Subscript_ extends @py_Subscript, Expr { - - /** Gets the value of this subscript expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the index of this subscript expression. */ - Expr getIndex() { - py_exprs(result, _, this, 3) - } - + Expr getIndex() { py_exprs(result, _, this, 3) } /** Gets the context of this subscript expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "Subscript" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "Subscript" } } library class TemplateDottedNotation_ extends @py_TemplateDottedNotation, Expr { - - /** Gets the object of this template dotted notation expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the attribute name of this template dotted notation expression. */ - string getAttr() { - py_strs(result, this, 3) - } - + string getAttr() { py_strs(result, this, 3) } /** Gets the context of this template dotted notation expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "TemplateDottedNotation" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "TemplateDottedNotation" } } library class TemplateWrite_ extends @py_TemplateWrite, Stmt { - - /** Gets the value of this template write statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "TemplateWrite" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "TemplateWrite" } } library class Try_ extends @py_Try, Stmt { - - /** Gets the body of this try statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 1) - } - + StmtList getBody() { py_stmt_lists(result, this, 1) } /** Gets the nth statement of this try statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this try statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the else block of this try statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 2) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 2) } /** Gets the nth else statement of this try statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an else statement of this try statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } /** Gets the exception handlers of this try statement. */ - StmtList getHandlers() { - py_stmt_lists(result, this, 3) - } - + StmtList getHandlers() { py_stmt_lists(result, this, 3) } /** Gets the nth exception handler of this try statement. */ - Stmt getHandler(int index) { - result = this.getHandlers().getItem(index) - } + Stmt getHandler(int index) { result = this.getHandlers().getItem(index) } /** Gets an exception handler of this try statement. */ - Stmt getAHandler() { - result = this.getHandlers().getAnItem() - } - + Stmt getAHandler() { result = this.getHandlers().getAnItem() } /** Gets the finally block of this try statement. */ - StmtList getFinalbody() { - py_stmt_lists(result, this, 4) - } - + StmtList getFinalbody() { py_stmt_lists(result, this, 4) } /** Gets the nth finally statement of this try statement. */ - Stmt getFinalstmt(int index) { - result = this.getFinalbody().getItem(index) - } + Stmt getFinalstmt(int index) { result = this.getFinalbody().getItem(index) } /** Gets a finally statement of this try statement. */ - Stmt getAFinalstmt() { - result = this.getFinalbody().getAnItem() - } - - override string toString() { - result = "Try" - } + Stmt getAFinalstmt() { result = this.getFinalbody().getAnItem() } + override string toString() { result = "Try" } } library class Tuple_ extends @py_Tuple, Expr { - - /** Gets the elements of this tuple expression. */ - ExprList getElts() { - py_expr_lists(result, this, 2) - } - + ExprList getElts() { py_expr_lists(result, this, 2) } /** Gets the nth element of this tuple expression. */ - Expr getElt(int index) { - result = this.getElts().getItem(index) - } + Expr getElt(int index) { result = this.getElts().getItem(index) } /** Gets an element of this tuple expression. */ - Expr getAnElt() { - result = this.getElts().getAnItem() - } - + Expr getAnElt() { result = this.getElts().getAnItem() } /** Gets the context of this tuple expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "Tuple" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "Tuple" } } library class UAdd_ extends @py_UAdd, Unaryop { - - override string toString() { - result = "UAdd" - } - + override string toString() { result = "UAdd" } } library class USub_ extends @py_USub, Unaryop { - - override string toString() { - result = "USub" - } - + override string toString() { result = "USub" } } library class UnaryExpr_ extends @py_UnaryExpr, Expr { - - /** Gets the operator of this unary expression. */ - Unaryop getOp() { - py_unaryops(result, _, this) - } - + Unaryop getOp() { py_unaryops(result, _, this) } /** Gets the operand of this unary expression. */ - Expr getOperand() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "UnaryExpr" - } + Expr getOperand() { py_exprs(result, _, this, 3) } + override string toString() { result = "UnaryExpr" } } library class While_ extends @py_While, Stmt { - - /** Gets the test of this while statement. */ - Expr getTest() { - py_exprs(result, _, this, 1) - } - + Expr getTest() { py_exprs(result, _, this, 1) } /** Gets the body of this while statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 2) - } - + StmtList getBody() { py_stmt_lists(result, this, 2) } /** Gets the nth statement of this while statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this while statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the else block of this while statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 3) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 3) } /** Gets the nth else statement of this while statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an else statement of this while statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - - override string toString() { - result = "While" - } + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } + override string toString() { result = "While" } } library class With_ extends @py_With, Stmt { - - /** Gets the context manager of this with statement. */ - Expr getContextExpr() { - py_exprs(result, _, this, 1) - } - + Expr getContextExpr() { py_exprs(result, _, this, 1) } /** Gets the optional variable of this with statement. */ - Expr getOptionalVars() { - py_exprs(result, _, this, 2) - } - + Expr getOptionalVars() { py_exprs(result, _, this, 2) } /** Gets the body of this with statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 3) - } - + StmtList getBody() { py_stmt_lists(result, this, 3) } /** Gets the nth statement of this with statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this with statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Whether the async property of this with statement is true. */ - predicate isAsync() { - py_bools(this, 4) - } - - override string toString() { - result = "With" - } + predicate isAsync() { py_bools(this, 4) } + override string toString() { result = "With" } } library class Yield_ extends @py_Yield, Expr { - - /** Gets the value of this yield expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Yield" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "Yield" } } library class YieldFrom_ extends @py_YieldFrom, Expr { - - /** Gets the value of this yield-from expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "YieldFrom" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "YieldFrom" } } library class Alias_ extends @py_alias { - - /** Gets the value of this alias. */ - Expr getValue() { - py_exprs(result, _, this, 0) - } - + Expr getValue() { py_exprs(result, _, this, 0) } /** Gets the name of this alias. */ - Expr getAsname() { - py_exprs(result, _, this, 1) - } + Expr getAsname() { py_exprs(result, _, this, 1) } - AliasList getParent() { - py_aliases(this, result, _) - } - - string toString() { - result = "Alias" - } + AliasList getParent() { py_aliases(this, result, _) } + string toString() { result = "Alias" } } library class AliasList_ extends @py_alias_list { - - Import getParent() { - py_alias_lists(this, result) - } + Import getParent() { py_alias_lists(this, result) } /** Gets an item of this alias list */ - Alias getAnItem() { - py_aliases(result, this, _) - } + Alias getAnItem() { py_aliases(result, this, _) } /** Gets the nth item of this alias list */ - Alias getItem(int index) { - py_aliases(result, this, index) - } - - string toString() { - result = "AliasList" - } + Alias getItem(int index) { py_aliases(result, this, index) } + string toString() { result = "AliasList" } } library class Arguments_ extends @py_arguments { - - /** Gets the keyword default values of this parameters definition. */ - ExprList getKwDefaults() { - py_expr_lists(result, this, 0) - } - + ExprList getKwDefaults() { py_expr_lists(result, this, 0) } /** Gets the nth keyword default value of this parameters definition. */ - Expr getKwDefault(int index) { - result = this.getKwDefaults().getItem(index) - } + Expr getKwDefault(int index) { result = this.getKwDefaults().getItem(index) } /** Gets a keyword default value of this parameters definition. */ - Expr getAKwDefault() { - result = this.getKwDefaults().getAnItem() - } - + Expr getAKwDefault() { result = this.getKwDefaults().getAnItem() } /** Gets the default values of this parameters definition. */ - ExprList getDefaults() { - py_expr_lists(result, this, 1) - } - + ExprList getDefaults() { py_expr_lists(result, this, 1) } /** Gets the nth default value of this parameters definition. */ - Expr getDefault(int index) { - result = this.getDefaults().getItem(index) - } + Expr getDefault(int index) { result = this.getDefaults().getItem(index) } /** Gets a default value of this parameters definition. */ - Expr getADefault() { - result = this.getDefaults().getAnItem() - } - + Expr getADefault() { result = this.getDefaults().getAnItem() } /** Gets the annotations of this parameters definition. */ - ExprList getAnnotations() { - py_expr_lists(result, this, 2) - } - + ExprList getAnnotations() { py_expr_lists(result, this, 2) } /** Gets the nth annotation of this parameters definition. */ - Expr getAnnotation(int index) { - result = this.getAnnotations().getItem(index) - } + Expr getAnnotation(int index) { result = this.getAnnotations().getItem(index) } /** Gets an annotation of this parameters definition. */ - Expr getAnAnnotation() { - result = this.getAnnotations().getAnItem() - } - + Expr getAnAnnotation() { result = this.getAnnotations().getAnItem() } /** Gets the *arg annotation of this parameters definition. */ - Expr getVarargannotation() { - py_exprs(result, _, this, 3) - } - + Expr getVarargannotation() { py_exprs(result, _, this, 3) } /** Gets the **kwarg annotation of this parameters definition. */ - Expr getKwargannotation() { - py_exprs(result, _, this, 4) - } - + Expr getKwargannotation() { py_exprs(result, _, this, 4) } /** Gets the kw_annotations of this parameters definition. */ - ExprList getKwAnnotations() { - py_expr_lists(result, this, 5) - } - + ExprList getKwAnnotations() { py_expr_lists(result, this, 5) } /** Gets the nth kw_annotation of this parameters definition. */ - Expr getKwAnnotation(int index) { - result = this.getKwAnnotations().getItem(index) - } + Expr getKwAnnotation(int index) { result = this.getKwAnnotations().getItem(index) } /** Gets a kw_annotation of this parameters definition. */ - Expr getAKwAnnotation() { - result = this.getKwAnnotations().getAnItem() - } + Expr getAKwAnnotation() { result = this.getKwAnnotations().getAnItem() } - ArgumentsParent getParent() { - py_arguments(this, result) - } - - string toString() { - result = "Arguments" - } + ArgumentsParent getParent() { py_arguments(this, result) } + string toString() { result = "Arguments" } } library class ArgumentsParent_ extends @py_arguments_parent { - - string toString() { - result = "ArgumentsParent" - } - + string toString() { result = "ArgumentsParent" } } library class AstNode_ extends @py_ast_node { - - string toString() { - result = "AstNode" - } - + string toString() { result = "AstNode" } } library class BoolParent_ extends @py_bool_parent { - - string toString() { - result = "BoolParent" - } - + string toString() { result = "BoolParent" } } library class Boolop_ extends @py_boolop { + BoolExpr getParent() { py_boolops(this, _, result) } - BoolExpr getParent() { - py_boolops(this, _, result) - } - - string toString() { - result = "Boolop" - } - + string toString() { result = "Boolop" } } library class Cmpop_ extends @py_cmpop { + CmpopList getParent() { py_cmpops(this, _, result, _) } - CmpopList getParent() { - py_cmpops(this, _, result, _) - } - - string toString() { - result = "Cmpop" - } - + string toString() { result = "Cmpop" } } library class CmpopList_ extends @py_cmpop_list { - - Compare getParent() { - py_cmpop_lists(this, result) - } + Compare getParent() { py_cmpop_lists(this, result) } /** Gets an item of this comparison operator list */ - Cmpop getAnItem() { - py_cmpops(result, _, this, _) - } + Cmpop getAnItem() { py_cmpops(result, _, this, _) } /** Gets the nth item of this comparison operator list */ - Cmpop getItem(int index) { - py_cmpops(result, _, this, index) - } - - string toString() { - result = "CmpopList" - } + Cmpop getItem(int index) { py_cmpops(result, _, this, index) } + string toString() { result = "CmpopList" } } library class Comprehension_ extends @py_comprehension { - - /** Gets the location of this comprehension. */ - Location getLocation() { - py_locations(result, this) - } - + Location getLocation() { py_locations(result, this) } /** Gets the iterable of this comprehension. */ - Expr getIter() { - py_exprs(result, _, this, 1) - } - + Expr getIter() { py_exprs(result, _, this, 1) } /** Gets the target of this comprehension. */ - Expr getTarget() { - py_exprs(result, _, this, 2) - } - + Expr getTarget() { py_exprs(result, _, this, 2) } /** Gets the conditions of this comprehension. */ - ExprList getIfs() { - py_expr_lists(result, this, 3) - } - + ExprList getIfs() { py_expr_lists(result, this, 3) } /** Gets the nth condition of this comprehension. */ - Expr getIf(int index) { - result = this.getIfs().getItem(index) - } + Expr getIf(int index) { result = this.getIfs().getItem(index) } /** Gets a condition of this comprehension. */ - Expr getAnIf() { - result = this.getIfs().getAnItem() - } + Expr getAnIf() { result = this.getIfs().getAnItem() } - ComprehensionList getParent() { - py_comprehensions(this, result, _) - } - - string toString() { - result = "Comprehension" - } + ComprehensionList getParent() { py_comprehensions(this, result, _) } + string toString() { result = "Comprehension" } } library class ComprehensionList_ extends @py_comprehension_list { - - ListComp getParent() { - py_comprehension_lists(this, result) - } + ListComp getParent() { py_comprehension_lists(this, result) } /** Gets an item of this comprehension list */ - Comprehension getAnItem() { - py_comprehensions(result, this, _) - } + Comprehension getAnItem() { py_comprehensions(result, this, _) } /** Gets the nth item of this comprehension list */ - Comprehension getItem(int index) { - py_comprehensions(result, this, index) - } - - string toString() { - result = "ComprehensionList" - } + Comprehension getItem(int index) { py_comprehensions(result, this, index) } + string toString() { result = "ComprehensionList" } } library class DictItem_ extends @py_dict_item { + DictItemList getParent() { py_dict_items(this, _, result, _) } - DictItemList getParent() { - py_dict_items(this, _, result, _) - } - - string toString() { - result = "DictItem" - } - + string toString() { result = "DictItem" } } library class DictItemList_ extends @py_dict_item_list { - - DictItemListParent getParent() { - py_dict_item_lists(this, result) - } + DictItemListParent getParent() { py_dict_item_lists(this, result) } /** Gets an item of this dict_item list */ - DictItem getAnItem() { - py_dict_items(result, _, this, _) - } + DictItem getAnItem() { py_dict_items(result, _, this, _) } /** Gets the nth item of this dict_item list */ - DictItem getItem(int index) { - py_dict_items(result, _, this, index) - } - - string toString() { - result = "DictItemList" - } + DictItem getItem(int index) { py_dict_items(result, _, this, index) } + string toString() { result = "DictItemList" } } library class DictItemListParent_ extends @py_dict_item_list_parent { - - string toString() { - result = "DictItemListParent" - } - + string toString() { result = "DictItemListParent" } } library class Expr_ extends @py_expr { - - /** Gets the location of this expression. */ - Location getLocation() { - py_locations(result, this) - } - + Location getLocation() { py_locations(result, this) } /** Whether the parenthesised property of this expression is true. */ - predicate isParenthesised() { - py_bools(this, 1) - } + predicate isParenthesised() { py_bools(this, 1) } - ExprParent getParent() { - py_exprs(this, _, result, _) - } - - string toString() { - result = "Expr" - } + ExprParent getParent() { py_exprs(this, _, result, _) } + string toString() { result = "Expr" } } library class ExprContext_ extends @py_expr_context { + ExprContextParent getParent() { py_expr_contexts(this, _, result) } - ExprContextParent getParent() { - py_expr_contexts(this, _, result) - } - - string toString() { - result = "ExprContext" - } - + string toString() { result = "ExprContext" } } library class ExprContextParent_ extends @py_expr_context_parent { - - string toString() { - result = "ExprContextParent" - } - + string toString() { result = "ExprContextParent" } } library class ExprList_ extends @py_expr_list { - - ExprListParent getParent() { - py_expr_lists(this, result, _) - } + ExprListParent getParent() { py_expr_lists(this, result, _) } /** Gets an item of this expression list */ - Expr getAnItem() { - py_exprs(result, _, this, _) - } + Expr getAnItem() { py_exprs(result, _, this, _) } /** Gets the nth item of this expression list */ - Expr getItem(int index) { - py_exprs(result, _, this, index) - } - - string toString() { - result = "ExprList" - } + Expr getItem(int index) { py_exprs(result, _, this, index) } + string toString() { result = "ExprList" } } library class ExprListParent_ extends @py_expr_list_parent { - - string toString() { - result = "ExprListParent" - } - + string toString() { result = "ExprListParent" } } library class ExprOrStmt_ extends @py_expr_or_stmt { - - string toString() { - result = "ExprOrStmt" - } - + string toString() { result = "ExprOrStmt" } } library class ExprParent_ extends @py_expr_parent { - - string toString() { - result = "ExprParent" - } - + string toString() { result = "ExprParent" } } library class Keyword_ extends @py_keyword, DictItem { - - /** Gets the location of this keyword argument. */ - override Location getLocation() { - py_locations(result, this) - } - + override Location getLocation() { py_locations(result, this) } /** Gets the value of this keyword argument. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the arg of this keyword argument. */ - string getArg() { - py_strs(result, this, 2) - } - - override string toString() { - result = "Keyword" - } + string getArg() { py_strs(result, this, 2) } + override string toString() { result = "Keyword" } } library class LocationParent_ extends @py_location_parent { - - string toString() { - result = "LocationParent" - } - + string toString() { result = "LocationParent" } } library class Operator_ extends @py_operator { + BinaryExpr getParent() { py_operators(this, _, result) } - BinaryExpr getParent() { - py_operators(this, _, result) - } - - string toString() { - result = "Operator" - } - + string toString() { result = "Operator" } } library class Parameter_ extends @py_parameter { - - string toString() { - result = "Parameter" - } - + string toString() { result = "Parameter" } } library class Scope_ extends @py_scope { - - string toString() { - result = "Scope" - } - + string toString() { result = "Scope" } } library class Stmt_ extends @py_stmt { - - /** Gets the location of this statement. */ - Location getLocation() { - py_locations(result, this) - } + Location getLocation() { py_locations(result, this) } - StmtList getParent() { - py_stmts(this, _, result, _) - } - - string toString() { - result = "Stmt" - } + StmtList getParent() { py_stmts(this, _, result, _) } + string toString() { result = "Stmt" } } library class StmtList_ extends @py_stmt_list { - - StmtListParent getParent() { - py_stmt_lists(this, result, _) - } + StmtListParent getParent() { py_stmt_lists(this, result, _) } /** Gets an item of this statement list */ - Stmt getAnItem() { - py_stmts(result, _, this, _) - } + Stmt getAnItem() { py_stmts(result, _, this, _) } /** Gets the nth item of this statement list */ - Stmt getItem(int index) { - py_stmts(result, _, this, index) - } - - string toString() { - result = "StmtList" - } + Stmt getItem(int index) { py_stmts(result, _, this, index) } + string toString() { result = "StmtList" } } library class StmtListParent_ extends @py_stmt_list_parent { - - string toString() { - result = "StmtListParent" - } - + string toString() { result = "StmtListParent" } } library class StringList_ extends @py_str_list { - - StrListParent getParent() { - py_str_lists(this, result) - } + StrListParent getParent() { py_str_lists(this, result) } /** Gets an item of this string list */ - string getAnItem() { - py_strs(result, this, _) - } + string getAnItem() { py_strs(result, this, _) } /** Gets the nth item of this string list */ - string getItem(int index) { - py_strs(result, this, index) - } - - string toString() { - result = "StringList" - } + string getItem(int index) { py_strs(result, this, index) } + string toString() { result = "StringList" } } library class StrListParent_ extends @py_str_list_parent { - - string toString() { - result = "StrListParent" - } - + string toString() { result = "StrListParent" } } library class StrParent_ extends @py_str_parent { - - string toString() { - result = "StrParent" - } - + string toString() { result = "StrParent" } } library class Unaryop_ extends @py_unaryop { + UnaryExpr getParent() { py_unaryops(this, _, result) } - UnaryExpr getParent() { - py_unaryops(this, _, result) - } - - string toString() { - result = "Unaryop" - } - + string toString() { result = "Unaryop" } } library class VariableParent_ extends @py_variable_parent { - - string toString() { - result = "VariableParent" - } - + string toString() { result = "VariableParent" } } - diff --git a/python/ql/src/semmle/python/Class.qll b/python/ql/src/semmle/python/Class.qll index 9cef58d4d81..daa68dcef4b 100644 --- a/python/ql/src/semmle/python/Class.qll +++ b/python/ql/src/semmle/python/Class.qll @@ -1,35 +1,40 @@ import python - -/** An (artificial) expression corresponding to a class definition. +/** + * An (artificial) expression corresponding to a class definition. * It is recommended to use `ClassDef` instead. */ class ClassExpr extends ClassExpr_ { - /** Gets the metaclass expression */ - Expr getMetaClass() { - if major_version() = 3 then - exists(Keyword metacls | this.getAKeyword() = metacls and metacls.getArg() = "metaclass" and result = metacls.getValue()) + Expr getMetaClass() { + if major_version() = 3 + then + exists(Keyword metacls | + this.getAKeyword() = metacls and + metacls.getArg() = "metaclass" and + result = metacls.getValue() + ) else - exists(Assign a | a = this.getInnerScope().getAStmt() and ((Name)a.getATarget()).getId() = "__metaclass__" and result = a.getValue()) + exists(Assign a | + a = this.getInnerScope().getAStmt() and + a.getATarget().(Name).getId() = "__metaclass__" and + result = a.getValue() + ) } - /** Gets the nth keyword argument of this class definition. */ override DictUnpackingOrKeyword getKeyword(int index) { result = this.getKeywords().getItem(index) } /** Gets a keyword argument of this class definition. */ - override DictUnpackingOrKeyword getAKeyword() { - result = this.getKeywords().getAnItem() - } + override DictUnpackingOrKeyword getAKeyword() { result = this.getKeywords().getAnItem() } override Expr getASubExpression() { - result = this.getABase() or - result = this.getAKeyword().getValue() or - result = this.getKwargs() or - result = this.getStarargs() + result = this.getABase() or + result = this.getAKeyword().getValue() or + result = this.getKwargs() or + result = this.getStarargs() } Call getADecoratorCall() { @@ -38,9 +43,7 @@ class ClassExpr extends ClassExpr_ { } /** Gets a decorator of this function expression */ - Expr getADecorator() { - result = this.getADecoratorCall().getFunc() - } + Expr getADecorator() { result = this.getADecoratorCall().getFunc() } override AstNode getAChildNode() { result = this.getASubExpression() @@ -49,151 +52,102 @@ class ClassExpr extends ClassExpr_ { } /** Gets a tuple (*) argument of this class definition. */ - Expr getStarargs() { - result = this.getABase().(Starred).getValue() - } + Expr getStarargs() { result = this.getABase().(Starred).getValue() } /** Gets a dictionary (**) argument of this class definition. */ - Expr getKwargs() { - result = this.getAKeyword().(DictUnpacking).getValue() - } - + Expr getKwargs() { result = this.getAKeyword().(DictUnpacking).getValue() } } /** A class statement. Note that ClassDef extends Assign as a class definition binds the newly created class */ class ClassDef extends Assign { - /* syntax: class name(...): ... */ - ClassDef() { /* This is an artificial assignment the rhs of which is a (possibly decorated) ClassExpr */ exists(ClassExpr c | this.getValue() = c or this.getValue() = c.getADecoratorCall()) } - override string toString() { - result = "ClassDef" - } + override string toString() { result = "ClassDef" } /** Gets the class for this statement */ Class getDefinedClass() { - exists(ClassExpr c | - this.getValue() = c or this.getValue() = c.getADecoratorCall() | + exists(ClassExpr c | this.getValue() = c or this.getValue() = c.getADecoratorCall() | result = c.getInnerScope() ) } - override Stmt getLastStatement() { - result = this.getDefinedClass().getLastStatement() - } - + override Stmt getLastStatement() { result = this.getDefinedClass().getLastStatement() } } /** The scope of a class. This is the scope of all the statements within the class definition */ class Class extends Class_, Scope, AstNode { - - /** Use getADecorator() instead of getDefinition().getADecorator() + /** + * Use getADecorator() instead of getDefinition().getADecorator() * Use getMetaClass() instead of getDefinition().getMetaClass() */ - deprecated ClassExpr getDefinition() { - result = this.getParent() - } + deprecated ClassExpr getDefinition() { result = this.getParent() } /** Gets a defined init method of this class */ - Function getInitMethod() { - result.getScope() = this and result.isInitMethod() - } + Function getInitMethod() { result.getScope() = this and result.isInitMethod() } /** Gets a method defined in this class */ - Function getAMethod() { - result.getScope() = this - } + Function getAMethod() { result.getScope() = this } - override Location getLocation() { - py_scope_location(result, this) - } + override Location getLocation() { py_scope_location(result, this) } /** Gets the scope (module, class or function) in which this class is defined */ - override Scope getEnclosingScope() { - result = this.getParent().getScope() - } + override Scope getEnclosingScope() { result = this.getParent().getScope() } /** Use getEnclosingScope() instead */ - override Scope getScope() { - result = this.getParent().getScope() - } + override Scope getScope() { result = this.getParent().getScope() } - override string toString() { - result = "Class " + this.getName() - } + override string toString() { result = "Class " + this.getName() } /** Gets the statements forming the body of this class */ - override StmtList getBody() { - result = Class_.super.getBody() - } + override StmtList getBody() { result = Class_.super.getBody() } /** Gets the nth statement in the class */ - override Stmt getStmt(int index) { - result = Class_.super.getStmt(index) - } + override Stmt getStmt(int index) { result = Class_.super.getStmt(index) } /** Gets a statement in the class */ - override Stmt getAStmt() { - result = Class_.super.getAStmt() - } + override Stmt getAStmt() { result = Class_.super.getAStmt() } /** Gets the name used to define this class */ - override string getName() { - result = Class_.super.getName() - } + override string getName() { result = Class_.super.getName() } - predicate hasSideEffects() { - any() - } + predicate hasSideEffects() { any() } /** Whether this is probably a mixin (has 'mixin' or similar in name or docstring) */ predicate isProbableMixin() { - (this.getName().toLowerCase().matches("%mixin%") - or - this.getDocString().getText().toLowerCase().matches("%mixin%") - or - this.getDocString().getText().toLowerCase().matches("%mix-in%") + ( + this.getName().toLowerCase().matches("%mixin%") + or + this.getDocString().getText().toLowerCase().matches("%mixin%") + or + this.getDocString().getText().toLowerCase().matches("%mix-in%") ) } - override AstNode getAChildNode() { - result = this.getAStmt() - } + override AstNode getAChildNode() { result = this.getAStmt() } - Expr getADecorator() { - result = this.getParent().getADecorator() - } + Expr getADecorator() { result = this.getParent().getADecorator() } /** Gets the metaclass expression */ - Expr getMetaClass() { - result = this.getParent().getMetaClass() - } + Expr getMetaClass() { result = this.getParent().getMetaClass() } /** Gets the ClassObject corresponding to this class */ - ClassObject getClassObject() { - result.getOrigin() = this.getParent() - } + ClassObject getClassObject() { result.getOrigin() = this.getParent() } /** Gets the nth base of this class definition. */ - Expr getBase(int index) { - result = this.getParent().getBase(index) - } + Expr getBase(int index) { result = this.getParent().getBase(index) } /** Gets a base of this class definition. */ - Expr getABase() { - result = this.getParent().getABase() - } + Expr getABase() { result = this.getParent().getABase() } /** Gets the metrics for this class */ - ClassMetrics getMetrics() { - result = this - } + ClassMetrics getMetrics() { result = this } - /** Gets the qualified name for this class. + /** + * Gets the qualified name for this class. * Should return the same name as the `__qualname__` attribute on classes in Python 3. */ string getQualifiedName() { @@ -202,20 +156,13 @@ class Class extends Class_, Scope, AstNode { exists(string enclosing_name | enclosing_name = this.getScope().(Function).getQualifiedName() or - enclosing_name = this.getScope().(Class).getQualifiedName() | + enclosing_name = this.getScope().(Class).getQualifiedName() + | result = enclosing_name + "." + this.getName() ) } - override - predicate containsInScope(AstNode inner) { - Scope.super.containsInScope(inner) - } - - override - predicate contains(AstNode inner) { - Scope.super.contains(inner) - } + override predicate containsInScope(AstNode inner) { Scope.super.containsInScope(inner) } + override predicate contains(AstNode inner) { Scope.super.contains(inner) } } - diff --git a/python/ql/src/semmle/python/Comment.qll b/python/ql/src/semmle/python/Comment.qll index c40de34478b..e0b33c1c94b 100644 --- a/python/ql/src/semmle/python/Comment.qll +++ b/python/ql/src/semmle/python/Comment.qll @@ -2,38 +2,28 @@ import python /** A source code comment */ class Comment extends @py_comment { - /** Gets the full text of the comment including the leading '#' */ - string getText() { - py_comments(this, result, _) - } + string getText() { py_comments(this, result, _) } /** Gets the contents of the comment excluding the leading '#' */ - string getContents() { - result = this.getText().suffix(1) - } + string getContents() { result = this.getText().suffix(1) } - Location getLocation() { - py_comments(this, _, result) + Location getLocation() { py_comments(this, _, result) } - } + string toString() { result = "Comment " + this.getText() } - string toString() { - result = "Comment " + this.getText() - } - - /** Gets this immediately following comment. + /** + * Gets this immediately following comment. * Blanks line are allowed between this comment and the following comment, * but code or other comments are not. */ Comment getFollowing() { - exists(File f, int n | - this.file_line(f, n) | - result.file_line(f, n+1) + exists(File f, int n | this.file_line(f, n) | + result.file_line(f, n + 1) or - result.file_line(f, n+2) and f.emptyLine(n+1) + result.file_line(f, n + 2) and f.emptyLine(n + 1) or - result.file_line(f, n+3) and f.emptyLine(n+2) and f.emptyLine(n+1) + result.file_line(f, n + 3) and f.emptyLine(n + 2) and f.emptyLine(n + 1) ) } @@ -41,47 +31,34 @@ class Comment extends @py_comment { this.getLocation().getFile() = f and this.getLocation().getStartLine() = n } - } private predicate comment_block_part(Comment start, Comment part, int i) { not exists(Comment prev | prev.getFollowing() = part) and exists(Comment following | part.getFollowing() = following) and - start = part and i = 1 + start = part and + i = 1 or exists(Comment prev | - comment_block_part(start, prev, i-1) and + comment_block_part(start, prev, i - 1) and part = prev.getFollowing() ) } /** A block of consecutive comments */ class CommentBlock extends @py_comment { + CommentBlock() { comment_block_part(this, _, _) } - CommentBlock() { - comment_block_part(this, _, _) - } + private Comment last() { comment_block_part(this, result, this.length()) } - private Comment last() { - comment_block_part(this, result, this.length()) - } - - string toString() { - result = "Comment block" - } + string toString() { result = "Comment block" } /** The length of this comment block (in comments) */ - int length() { - result = max(int i | comment_block_part(this, _, i)) - } + int length() { result = max(int i | comment_block_part(this, _, i)) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { - ((Comment)this).getLocation().hasLocationInfo(filepath, bl, bc, _, _) - and - exists(Comment end | - end = this.last() | - end.getLocation().hasLocationInfo(_, _, _, el, ec) - ) + this.(Comment).getLocation().hasLocationInfo(filepath, bl, bc, _, _) and + exists(Comment end | end = this.last() | end.getLocation().hasLocationInfo(_, _, _, el, ec)) } predicate contains(Comment c) { @@ -91,20 +68,18 @@ class CommentBlock extends @py_comment { } string getContents() { - result = concat(Comment c,int i | - comment_block_part(this, c, i) or this = c and i = 0 | - c.getContents() order by i - ) + result = + concat(Comment c, int i | + comment_block_part(this, c, i) + or + this = c and i = 0 + | + c.getContents() order by i + ) } - } /** A type-hint comment. Any comment that starts with `# type:` */ class TypeHintComment extends Comment { - - TypeHintComment() { - this.getText().regexpMatch("# +type:.*") - } - + TypeHintComment() { this.getText().regexpMatch("# +type:.*") } } - diff --git a/python/ql/src/semmle/python/Comparisons.qll b/python/ql/src/semmle/python/Comparisons.qll index 5bb7973e7b6..b6cd9ca800c 100644 --- a/python/ql/src/semmle/python/Comparisons.qll +++ b/python/ql/src/semmle/python/Comparisons.qll @@ -1,48 +1,64 @@ - import python /** A class representing the six comparison operators, ==, !=, <, <=, > and >=. */ class CompareOp extends int { - - CompareOp() { - this in [1..6] - } + CompareOp() { this in [1 .. 6] } /** Gets the logical inverse operator */ CompareOp invert() { - this = eq() and result = ne() or - this = ne() and result = eq() or - this = lt() and result = ge() or - this = gt() and result = le() or - this = le() and result = gt() or + this = eq() and result = ne() + or + this = ne() and result = eq() + or + this = lt() and result = ge() + or + this = gt() and result = le() + or + this = le() and result = gt() + or this = ge() and result = lt() } - /** Gets the reverse operator (swapping the operands) */ + /** Gets the reverse operator (swapping the operands) */ CompareOp reverse() { - this = eq() and result = eq() or - this = ne() and result = ne() or - this = lt() and result = gt() or - this = gt() and result = lt() or - this = le() and result = ge() or + this = eq() and result = eq() + or + this = ne() and result = ne() + or + this = lt() and result = gt() + or + this = gt() and result = lt() + or + this = le() and result = ge() + or this = ge() and result = le() } string repr() { - this = eq() and result = "==" or - this = ne() and result = "!=" or - this = lt() and result = "<" or - this = gt() and result = ">" or - this = le() and result = "<=" or + this = eq() and result = "==" + or + this = ne() and result = "!=" + or + this = lt() and result = "<" + or + this = gt() and result = ">" + or + this = le() and result = "<=" + or this = ge() and result = ">=" } predicate forOp(Cmpop op) { - op instanceof Eq and this = eq() or - op instanceof NotEq and this = ne() or - op instanceof Lt and this = lt() or - op instanceof LtE and this = le() or - op instanceof Gt and this = gt() or + op instanceof Eq and this = eq() + or + op instanceof NotEq and this = ne() + or + op instanceof Lt and this = lt() + or + op instanceof LtE and this = le() + or + op instanceof Gt and this = gt() + or op instanceof GtE and this = ge() } @@ -52,31 +68,37 @@ class CompareOp extends int { or result = this.invert() and isTrue = false } - } CompareOp eq() { result = 1 } + CompareOp ne() { result = 2 } + CompareOp lt() { result = 3 } + CompareOp le() { result = 4 } + CompareOp gt() { result = 5 } + CompareOp ge() { result = 6 } /* Workaround precision limits in floating point numbers */ -bindingset[x] private predicate ok_magnitude(float x) { - x > -9007199254740992.0 // -2**53 - and +bindingset[x] +private predicate ok_magnitude(float x) { + x > -9007199254740992.0 and // -2**53 x < 9007199254740992.0 // 2**53 } -bindingset[x,y] private float add(float x, float y) { +bindingset[x, y] +private float add(float x, float y) { ok_magnitude(x) and ok_magnitude(y) and ok_magnitude(result) and result = x + y } -bindingset[x,y] private float sub(float x, float y) { +bindingset[x, y] +private float sub(float x, float y) { ok_magnitude(x) and ok_magnitude(y) and ok_magnitude(result) and @@ -84,7 +106,9 @@ bindingset[x,y] private float sub(float x, float y) { } /** Normalise equality cmp into the form `left op right + k`. */ -private predicate test(ControlFlowNode cmp, ControlFlowNode left, CompareOp op, ControlFlowNode right, float k) { +private predicate test( + ControlFlowNode cmp, ControlFlowNode left, CompareOp op, ControlFlowNode right, float k +) { simple_test(cmp, left, op, right) and k = 0 or add_test(cmp, left, op, right, k) @@ -98,82 +122,106 @@ private predicate test(ControlFlowNode cmp, ControlFlowNode left, CompareOp op, /** Various simple tests in left op right + k form. */ private predicate simple_test(CompareNode cmp, ControlFlowNode l, CompareOp cmpop, ControlFlowNode r) { - exists(Cmpop op | - cmp.operands(l, op, r) and cmpop.forOp(op) - ) + exists(Cmpop op | cmp.operands(l, op, r) and cmpop.forOp(op)) } -private predicate add_test_left(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { - exists(BinaryExprNode lhs, float c, float x, Num n | +private predicate add_test_left( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { + exists(BinaryExprNode lhs, float c, float x, Num n | lhs.getNode().getOp() instanceof Add and - test(cmp, lhs, op, r, c) and x = n.getN().toFloat() and k = sub(c, x) | + test(cmp, lhs, op, r, c) and + x = n.getN().toFloat() and + k = sub(c, x) + | l = lhs.getLeft() and n = lhs.getRight().getNode() or l = lhs.getRight() and n = lhs.getLeft().getNode() ) } -private predicate add_test_right(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +private predicate add_test_right( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { exists(BinaryExprNode rhs, float c, float x, Num n | rhs.getNode().getOp() instanceof Add and - test(cmp, l, op, rhs, c) and x = n.getN().toFloat() and k = add(c, x) | + test(cmp, l, op, rhs, c) and + x = n.getN().toFloat() and + k = add(c, x) + | r = rhs.getLeft() and n = rhs.getRight().getNode() or r = rhs.getRight() and n = rhs.getLeft().getNode() ) } -/* left + x op right + c => left op right + (c-x) - left op (right + x) + c => left op right + (c+x) */ -private predicate add_test(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +/* + * left + x op right + c => left op right + (c-x) + * left op (right + x) + c => left op right + (c+x) + */ + +private predicate add_test( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { add_test_left(cmp, l, op, r, k) or - add_test_right(cmp, l, op ,r, k) + add_test_right(cmp, l, op, r, k) } -private predicate subtract_test_left(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { - exists(BinaryExprNode lhs, float c, float x, Num n | +private predicate subtract_test_left( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { + exists(BinaryExprNode lhs, float c, float x, Num n | lhs.getNode().getOp() instanceof Sub and test(cmp, lhs, op, r, c) and - l = lhs.getLeft() and n = lhs.getRight().getNode() and - x = n.getN().toFloat() | + l = lhs.getLeft() and + n = lhs.getRight().getNode() and + x = n.getN().toFloat() + | k = add(c, x) ) } -private predicate subtract_test_right(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +private predicate subtract_test_right( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { exists(BinaryExprNode rhs, float c, float x, Num n | rhs.getNode().getOp() instanceof Sub and test(cmp, l, op, rhs, c) and - r = rhs.getRight() and n = rhs.getLeft().getNode() and - x = n.getN().toFloat() | + r = rhs.getRight() and + n = rhs.getLeft().getNode() and + x = n.getN().toFloat() + | k = sub(c, x) ) } -/* left - x op right + c => left op right + (c+x) - left op (right - x) + c => left op right + (c-x) */ -private predicate subtract_test(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +/* + * left - x op right + c => left op right + (c+x) + * left op (right - x) + c => left op right + (c-x) + */ + +private predicate subtract_test( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { subtract_test_left(cmp, l, op, r, k) or subtract_test_right(cmp, l, op, r, k) } -private predicate not_test(UnaryExprNode u, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { - u.getNode().getOp() instanceof Not - and +private predicate not_test( + UnaryExprNode u, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { + u.getNode().getOp() instanceof Not and test(u.getOperand(), l, op.invert(), r, k) } - -/** A comparison which can be simplified to the canonical form `x OP y + k` where `x` and `y` are `ControlFlowNode`s, +/** + * A comparison which can be simplified to the canonical form `x OP y + k` where `x` and `y` are `ControlFlowNode`s, * `k` is a floating point constant and `OP` is one of `<=`, `>`, `==` or `!=`. */ class Comparison extends ControlFlowNode { - - Comparison() { - test(this, _, _, _, _) - } + Comparison() { test(this, _, _, _, _) } /** Whether this condition tests `l op r + k` */ predicate tests(ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { @@ -182,14 +230,14 @@ class Comparison extends ControlFlowNode { /** Whether this condition tests `l op k` */ predicate tests(ControlFlowNode l, CompareOp op, float k) { - exists(ControlFlowNode r, float x, float c | - test(this, l, op, r, c) | + exists(ControlFlowNode r, float x, float c | test(this, l, op, r, c) | x = r.getNode().(Num).getN().toFloat() and k = add(c, x) ) } - /* The following predicates determine whether this test, when its result is `thisIsTrue`, + /* + * The following predicates determine whether this test, when its result is `thisIsTrue`, * is equivalent to the predicate `v OP k` or `v1 OP v2 + k`. * For example, the test `x <= y` being false, is equivalent to the predicate `x > y`. */ @@ -242,7 +290,8 @@ class Comparison extends ControlFlowNode { this.tests(v1.getAUse(), ge().conditional(thisIsTrue), v2.getAUse(), k) } - /** Whether the result of this comparison being `thisIsTrue` implies that the result of `that` is `isThatTrue`. + /** + * Whether the result of this comparison being `thisIsTrue` implies that the result of `that` is `isThatTrue`. * In other words, does the predicate that is equivalent to the result of `this` being `thisIsTrue` * imply the predicate that is equivalent to the result of `that` being `thatIsTrue`. * For example, assume that there are two tests, which when normalised have the form `x < y` and `x > y + 1`. @@ -315,7 +364,7 @@ class Comparison extends ControlFlowNode { this.equivalentToGt(thisIsTrue, v, k1) and that.equivalentToGtEq(thatIsTrue, v, k2) and ge(k1, k2) - or + or /* `v >= k1` => `v > k2` iff k1 > k2 */ this.equivalentToGtEq(thisIsTrue, v, k1) and that.equivalentToGt(thatIsTrue, v, k2) and @@ -402,7 +451,6 @@ class Comparison extends ControlFlowNode { ge(k1, k2) ) } - } /* Work around differences in floating-point comparisons between Python and QL */ @@ -412,41 +460,27 @@ private predicate is_zero(float x) { x = -0.0 } -bindingset[x,y] private predicate lt(float x, float y) { - if is_zero(x) then - y > 0 - else - x < y -} +bindingset[x, y] +private predicate lt(float x, float y) { if is_zero(x) then y > 0 else x < y } -bindingset[x,y] private predicate eq(float x, float y) { - if is_zero(x) then - is_zero(y) - else - x = y -} +bindingset[x, y] +private predicate eq(float x, float y) { if is_zero(x) then is_zero(y) else x = y } -bindingset[x,y] private predicate gt(float x, float y) { - lt(y, x) -} +bindingset[x, y] +private predicate gt(float x, float y) { lt(y, x) } -bindingset[x,y] private predicate le(float x, float y) { - lt(x, y) or eq(x, y) -} +bindingset[x, y] +private predicate le(float x, float y) { lt(x, y) or eq(x, y) } -bindingset[x,y] private predicate ge(float x, float y) { - lt(y, x) or eq(x, y) -} +bindingset[x, y] +private predicate ge(float x, float y) { lt(y, x) or eq(x, y) } - -/** A basic block which terminates in a condition, splitting the subsequent control flow, +/** + * A basic block which terminates in a condition, splitting the subsequent control flow, * in which the condition is an instance of `Comparison` */ class ComparisonControlBlock extends ConditionBlock { - - ComparisonControlBlock() { - this.getLastNode() instanceof Comparison - } + ComparisonControlBlock() { this.getLastNode() instanceof Comparison } /** Whether this conditional guard determines that, in block `b`, `l == r + k` if `eq` is true, or `l != r + k` if `eq` is false, */ predicate controls(ControlFlowNode l, CompareOp op, ControlFlowNode r, float k, BasicBlock b) { @@ -466,16 +500,13 @@ class ComparisonControlBlock extends ConditionBlock { ) } - Comparison getTest() { - this.getLastNode() = result - } + Comparison getTest() { this.getLastNode() = result } /** Whether this conditional guard implies that, in block `b`, the result of `that` is `thatIsTrue` */ predicate impliesThat(BasicBlock b, Comparison that, boolean thatIsTrue) { exists(boolean controlSense | - this.controls(b, controlSense) and + this.controls(b, controlSense) and this.getTest().impliesThat(controlSense, that, thatIsTrue) ) } - } diff --git a/python/ql/src/semmle/python/Comprehensions.qll b/python/ql/src/semmle/python/Comprehensions.qll index eec5dd372f6..d3cd82d4fd6 100644 --- a/python/ql/src/semmle/python/Comprehensions.qll +++ b/python/ql/src/semmle/python/Comprehensions.qll @@ -1,8 +1,7 @@ import python - + /** Base class for list, set and dictionary comprehensions, and generator expressions. */ abstract class Comp extends Expr { - abstract Function getFunction(); /** Gets the iteration variable for the nth innermost generator of this list comprehension */ @@ -13,35 +12,30 @@ abstract class Comp extends Expr { private For getNthInnerLoop(int n) { n = 0 and result = this.getFunction().getStmt(0) or - result = this.getNthInnerLoop(n-1).getStmt(0) + result = this.getNthInnerLoop(n - 1).getStmt(0) } /** Gets the iteration variable for a generator of this list comprehension */ - Variable getAnIterationVariable() { - result = this.getIterationVariable(_) - } + Variable getAnIterationVariable() { result = this.getIterationVariable(_) } /** Gets the scope in which the body of this list comprehension evaluates. */ - Scope getEvaluatingScope() { - result = this.getFunction() - } + Scope getEvaluatingScope() { result = this.getFunction() } /** Gets the expression for elements of this comprehension. */ Expr getElt() { exists(Yield yield, Stmt body | result = yield.getValue() and - body = this.getNthInnerLoop(_).getAStmt() | + body = this.getNthInnerLoop(_).getAStmt() + | yield = body.(ExprStmt).getValue() or yield = body.(If).getStmt(0).(ExprStmt).getValue() ) } - } /** A list comprehension, such as `[ chr(x) for x in range(ord('A'), ord('Z')+1) ]` */ class ListComp extends ListComp_, Comp { - override Expr getASubExpression() { result = this.getAGenerator().getASubExpression() or result = this.getElt() or @@ -54,9 +48,7 @@ class ListComp extends ListComp_, Comp { result = this.getFunction() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } /** Gets the scope in which the body of this list comprehension evaluates. */ override Scope getEvaluatingScope() { @@ -66,89 +58,53 @@ class ListComp extends ListComp_, Comp { } /** Gets the iteration variable for the nth innermost generator of this list comprehension */ - override Variable getIterationVariable(int n) { - result = Comp.super.getIterationVariable(n) - } + override Variable getIterationVariable(int n) { result = Comp.super.getIterationVariable(n) } - override Function getFunction() { - result = ListComp_.super.getFunction() - } + override Function getFunction() { result = ListComp_.super.getFunction() } - override string toString() { - result = ListComp_.super.toString() - } - - override Expr getElt() { - result = Comp.super.getElt() - } + override string toString() { result = ListComp_.super.toString() } + override Expr getElt() { result = Comp.super.getElt() } } - /** A set comprehension such as `{ v for v in "0123456789" }` */ class SetComp extends SetComp_, Comp { - - override Expr getASubExpression() { - result = this.getIterable() - } + override Expr getASubExpression() { result = this.getIterable() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getFunction() } - override predicate hasSideEffects() { - any() - } - - override Function getFunction() { - result = SetComp_.super.getFunction() - } + override predicate hasSideEffects() { any() } + override Function getFunction() { result = SetComp_.super.getFunction() } } /** A dictionary comprehension, such as `{ k:v for k, v in enumerate("0123456789") }` */ class DictComp extends DictComp_, Comp { - - override Expr getASubExpression() { - result = this.getIterable() - } + override Expr getASubExpression() { result = this.getIterable() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getFunction() } - override predicate hasSideEffects() { - any() - } - - override Function getFunction() { - result = DictComp_.super.getFunction() - } + override predicate hasSideEffects() { any() } + override Function getFunction() { result = DictComp_.super.getFunction() } } - /** A generator expression, such as `(var for var in iterable)` */ class GeneratorExp extends GeneratorExp_, Comp { - - override Expr getASubExpression() { - result = this.getIterable() - } + override Expr getASubExpression() { result = this.getIterable() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getFunction() } - override predicate hasSideEffects() { - any() - } - - override Function getFunction() { - result = GeneratorExp_.super.getFunction() - } + override predicate hasSideEffects() { any() } + override Function getFunction() { result = GeneratorExp_.super.getFunction() } } - diff --git a/python/ql/src/semmle/python/Constants.qll b/python/ql/src/semmle/python/Constants.qll index c95f6bf9dc5..6ca694a3ad1 100644 --- a/python/ql/src/semmle/python/Constants.qll +++ b/python/ql/src/semmle/python/Constants.qll @@ -8,30 +8,25 @@ int major_version() { or not explicit_major_version(_) and /* If there is more than one version, prefer 2 for backwards compatibilty */ - ( - if py_flags_versioned("version.major", "2", "2") then - result = 2 - else - result = 3 - ) + (if py_flags_versioned("version.major", "2", "2") then result = 2 else result = 3) } /** the Python minor version number */ int minor_version() { exists(string v | py_flags_versioned("version.minor", v, major_version().toString()) | - result = v.toInt()) - + result = v.toInt() + ) } /** the Python micro version number */ int micro_version() { exists(string v | py_flags_versioned("version.micro", v, major_version().toString()) | - result = v.toInt()) + result = v.toInt() + ) } private predicate explicit_major_version(int v) { - exists(string version | - py_flags_versioned("language.version", version, _) | + exists(string version | py_flags_versioned("language.version", version, _) | version.charAt(0) = "2" and v = 2 or version.charAt(0) = "3" and v = 3 diff --git a/python/ql/src/semmle/python/Exprs.qll b/python/ql/src/semmle/python/Exprs.qll index 37e8611e925..2b58fe38e4e 100644 --- a/python/ql/src/semmle/python/Exprs.qll +++ b/python/ql/src/semmle/python/Exprs.qll @@ -4,26 +4,19 @@ private import semmle.python.objects.ObjectInternal /** An expression */ class Expr extends Expr_, AstNode { - /** Gets the scope of this expression */ - override Scope getScope() { - py_scopes(this, result) - } + override Scope getScope() { py_scopes(this, result) } - override string toString() { - result = "Expression" - } + override string toString() { result = "Expression" } /** Gets the module in which this expression occurs */ - Module getEnclosingModule() { - result = this.getScope().getEnclosingModule() - } + Module getEnclosingModule() { result = this.getScope().getEnclosingModule() } - /** Whether this expression defines variable `v` - * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. */ - predicate defines(Variable v) { - this.getASubExpression+().defines(v) - } + /** + * Whether this expression defines variable `v` + * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. + */ + predicate defines(Variable v) { this.getASubExpression+().defines(v) } /** Whether this expression may have a side effect (as determined purely from its syntax) */ predicate hasSideEffects() { @@ -34,66 +27,57 @@ class Expr extends Expr_, AstNode { } /** Whether this expression is a constant */ - predicate isConstant() { - not this.isVariable() - } + predicate isConstant() { not this.isVariable() } /** Use isParenthesized instead. */ - override deprecated predicate isParenthesised() { - this.isParenthesized() - } + deprecated override predicate isParenthesised() { this.isParenthesized() } /** Whether the parenthesized property of this expression is true. */ - predicate isParenthesized() { - Expr_.super.isParenthesised() - } + predicate isParenthesized() { Expr_.super.isParenthesised() } private predicate isVariable() { - this.hasSideEffects() or - this instanceof Name or + this.hasSideEffects() + or + this instanceof Name + or exists(Expr e | e = this.getASubExpression() and e.isVariable()) } - override Location getLocation() { - result = Expr_.super.getLocation() - } + override Location getLocation() { result = Expr_.super.getLocation() } /** Gets an immediate (non-nested) sub-expression of this expression */ - Expr getASubExpression() { - none() - } + Expr getASubExpression() { none() } /** Use StrConst.getText() instead */ - deprecated string strValue() { - none() - } + deprecated string strValue() { none() } - override AstNode getAChildNode() { - result = this.getASubExpression() - } + override AstNode getAChildNode() { result = this.getASubExpression() } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. * Gets what this expression might "refer-to". Performs a combination of localized (intra-procedural) points-to * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly - * precise, but may not provide information for a significant number of flow-nodes. + * precise, but may not provide information for a significant number of flow-nodes. * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. - * NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use + * NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use * `ControlFlowNode.refersTo(...)` instead. */ predicate refersTo(Object obj, ClassObject cls, AstNode origin) { this.refersTo(_, obj, cls, origin) } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. * Gets what this expression might "refer-to" in the given `context`. */ predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) { this.getAFlowNode().refersTo(context, obj, cls, origin.getAFlowNode()) } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Holds if this expression might "refer-to" to `value` which is from `origin` - * Unlike `this.refersTo(value, _, origin)`, this predicate includes results + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Holds if this expression might "refer-to" to `value` which is from `origin` + * Unlike `this.refersTo(value, _, origin)`, this predicate includes results * where the class cannot be inferred. */ pragma[nomagic] @@ -101,36 +85,34 @@ class Expr extends Expr_, AstNode { this.getAFlowNode().refersTo(obj, origin.getAFlowNode()) } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Equivalent to `this.refersTo(value, _)` */ - predicate refersTo(Object obj) { - this.refersTo(obj, _) - } + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Equivalent to `this.refersTo(value, _)` + */ + predicate refersTo(Object obj) { this.refersTo(obj, _) } - /** Holds if this expression might "point-to" to `value` which is from `origin` + /** + * Holds if this expression might "point-to" to `value` which is from `origin` * in the given `context`. */ predicate pointsTo(Context context, Value value, AstNode origin) { this.getAFlowNode().pointsTo(context, value, origin.getAFlowNode()) } - /** Holds if this expression might "point-to" to `value` which is from `origin`. + /** + * Holds if this expression might "point-to" to `value` which is from `origin`. */ predicate pointsTo(Value value, AstNode origin) { this.getAFlowNode().pointsTo(value, origin.getAFlowNode()) } - /** Holds if this expression might "point-to" to `value`. + /** + * Holds if this expression might "point-to" to `value`. */ - predicate pointsTo(Value value) { - this.pointsTo(value, _) - } + predicate pointsTo(Value value) { this.pointsTo(value, _) } /** Gets a value that this expression might "point-to". */ - Value pointsTo() { - this.pointsTo(result) - } - + Value pointsTo() { this.pointsTo(result) } } /** An assignment expression, such as `x := y` */ @@ -143,103 +125,82 @@ class AssignExpr extends AssignExpr_ { /** An attribute expression, such as `value.attr` */ class Attribute extends Attribute_ { - /* syntax: Expr.name */ - - override Expr getASubExpression() { - result = this.getObject() - } + override Expr getASubExpression() { result = this.getObject() } override AttrNode getAFlowNode() { result = super.getAFlowNode() } - /** Gets the name of this attribute. That is the `name` in `obj.name` */ - string getName() { - result = Attribute_.super.getAttr() - } + string getName() { result = Attribute_.super.getAttr() } /** Gets the object of this attribute. That is the `obj` in `obj.name` */ - Expr getObject() { - result = Attribute_.super.getValue() - } + Expr getObject() { result = Attribute_.super.getValue() } - /** Gets the expression corresponding to the object of the attribute, if the name of the attribute is `name`. - * Equivalent to `this.getObject() and this.getName() = name`. */ + /** + * Gets the expression corresponding to the object of the attribute, if the name of the attribute is `name`. + * Equivalent to `this.getObject() and this.getName() = name`. + */ Expr getObject(string name) { result = Attribute_.super.getValue() and name = Attribute_.super.getAttr() } - } /** A subscript expression, such as `value[slice]` */ class Subscript extends Subscript_ { - /* syntax: Expr[Expr] */ - override Expr getASubExpression() { result = this.getIndex() or result = this.getObject() } - Expr getObject() { - result = Subscript_.super.getValue() - } + Expr getObject() { result = Subscript_.super.getValue() } override SubscriptNode getAFlowNode() { result = super.getAFlowNode() } } /** A call expression, such as `func(...)` */ class Call extends Call_ { - /* syntax: Expr(...) */ - override Expr getASubExpression() { result = this.getAPositionalArg() or result = this.getAKeyword().getValue() or result = this.getFunc() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } - override string toString() { - result = this.getFunc().toString() + "()" - } + override string toString() { result = this.getFunc().toString() + "()" } override CallNode getAFlowNode() { result = super.getAFlowNode() } /** Gets a tuple (*) argument of this call. */ - Expr getStarargs() { - result = this.getAPositionalArg().(Starred).getValue() - } + Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() } /** Gets a dictionary (**) argument of this call. */ - Expr getKwargs() { - result = this.getANamedArg().(DictUnpacking).getValue() - } + Expr getKwargs() { result = this.getANamedArg().(DictUnpacking).getValue() } /* Backwards compatibility */ - - /** Gets the nth keyword argument of this call expression, provided it is not preceded by a double-starred argument. + /** + * Gets the nth keyword argument of this call expression, provided it is not preceded by a double-starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getNamedArg(index) instead. - * */ + */ Keyword getKeyword(int index) { - result = this.getNamedArg(index) and not exists(DictUnpacking d, int lower | d = this.getNamedArg(lower) and lower < index) + result = this.getNamedArg(index) and + not exists(DictUnpacking d, int lower | d = this.getNamedArg(lower) and lower < index) } - /** Gets a keyword argument of this call expression, provided it is not preceded by a double-starred argument. + /** + * Gets a keyword argument of this call expression, provided it is not preceded by a double-starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getANamedArg() instead. - * */ - Keyword getAKeyword() { - result = this.getKeyword(_) - } + */ + Keyword getAKeyword() { result = this.getKeyword(_) } - /** Gets the positional argument at `index`, provided it is not preceded by a starred argument. + /** + * Gets the positional argument at `index`, provided it is not preceded by a starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getPositionalArg(index) instead. */ @@ -249,13 +210,12 @@ class Call extends Call_ { not exists(Starred s, int lower | s = this.getPositionalArg(lower) and lower < index) } - /** Gets a positional argument, provided it is not preceded by a starred argument. + /** + * Gets a positional argument, provided it is not preceded by a starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getAPositionalArg() instead. */ - Expr getAnArg() { - result = this.getArg(_) - } + Expr getAnArg() { result = this.getArg(_) } override AstNode getAChildNode() { result = this.getAPositionalArg() or @@ -281,14 +241,11 @@ class Call extends Call_ { count(this.getStarargs()) < 2 and result = getStarargs() } - } /** A conditional expression such as, `body if test else orelse` */ class IfExp extends IfExp_ { - /* syntax: Expr if Expr else Expr */ - override Expr getASubExpression() { result = this.getTest() or result = this.getBody() or result = this.getOrelse() } @@ -298,151 +255,96 @@ class IfExp extends IfExp_ { /** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */ class Starred extends Starred_ { - /* syntax: *Expr */ - - override Expr getASubExpression() { - result = this.getValue() - } - + override Expr getASubExpression() { result = this.getValue() } } - /** A yield expression, such as `yield value` */ class Yield extends Yield_ { - /* syntax: yield Expr */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override predicate hasSideEffects() { - any() - } - + override predicate hasSideEffects() { any() } } /** A yield expression, such as `yield from value` */ class YieldFrom extends YieldFrom_ { - /* syntax: yield from Expr */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override predicate hasSideEffects() { - any() - } - + override predicate hasSideEffects() { any() } } /** A repr (backticks) expression, such as `` `value` `` */ class Repr extends Repr_ { - /* syntax: `Expr` */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override predicate hasSideEffects() { - any() - } - + override predicate hasSideEffects() { any() } } /* Constants */ - -/** A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as - * `"hello"` are treated as Bytes for Python2, but Unicode for Python3. */ +/** + * A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as + * `"hello"` are treated as Bytes for Python2, but Unicode for Python3. + */ class Bytes extends StrConst { - /* syntax: b"hello" */ - - Bytes() { - not this.isUnicode() - } + Bytes() { not this.isUnicode() } override Object getLiteralObject() { py_cobjecttypes(result, theBytesType()) and py_cobjectnames(result, this.quotedString()) } - /** The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). + /** + * The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). * The following predicate help us match up a string/byte literals in the source * which the equivalent object. */ private string quotedString() { - exists(string b_unquoted | - b_unquoted = this.getS() | - result = "b'" + b_unquoted + "'" - ) + exists(string b_unquoted | b_unquoted = this.getS() | result = "b'" + b_unquoted + "'") } - } /** An ellipsis expression, such as `...` */ class Ellipsis extends Ellipsis_ { - /* syntax: ... */ - - override Expr getASubExpression() { - none() - } - + override Expr getASubExpression() { none() } } -/** Immutable literal expressions (except tuples). +/** + * Immutable literal expressions (except tuples). * Consists of string (both unicode and byte) literals and numeric literals. */ abstract class ImmutableLiteral extends Expr { - abstract Object getLiteralObject(); abstract boolean booleanValue(); - final Value getLiteralValue() { - result.(ConstantObjectInternal).getLiteral() = this - } - + final Value getLiteralValue() { result.(ConstantObjectInternal).getLiteral() = this } } /** A numerical constant expression, such as `7` or `4.2` */ abstract class Num extends Num_, ImmutableLiteral { - - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } /* We want to declare this abstract, but currently we cannot. */ - override string toString() { - result = "Num with missing toString" - } - + override string toString() { result = "Num with missing toString" } } /** An integer numeric constant, such as `7` or `0x9` */ class IntegerLiteral extends Num { - /* syntax: 4 */ - - IntegerLiteral() { - not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral - } + IntegerLiteral() { not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral } /** * Gets the (integer) value of this constant. Will not return a result if the value does not fit into - * a 32 bit signed value + * a 32 bit signed value */ - int getValue() { - result = this.getN().toInt() - } + int getValue() { result = this.getN().toInt() } - override string toString() { - result = "IntegerLiteral" - } + override string toString() { result = "IntegerLiteral" } override Object getLiteralObject() { py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, this.getN()) @@ -455,29 +357,22 @@ class IntegerLiteral extends Num { or this.getValue() != 0 and result = true } - } /** A floating point numeric constant, such as `0.4` or `4e3` */ class FloatLiteral extends Num { - /* syntax: 4.2 */ - FloatLiteral() { not this instanceof ImaginaryLiteral and this.getN().regexpMatch(".*[.eE].*") } - float getValue() { - result = this.getN().toFloat() - } + float getValue() { result = this.getN().toFloat() } - override string toString() { - result = "FloatLiteral" - } + override string toString() { result = "FloatLiteral" } override Object getLiteralObject() { - py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN()) + py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN()) } override boolean booleanValue() { @@ -495,22 +390,15 @@ class ImaginaryLiteral extends Num { private float value; /* syntax: 1.0j */ - - ImaginaryLiteral() { - value = this.getN().regexpCapture("(.+)j.*", 1).toFloat() - } + ImaginaryLiteral() { value = this.getN().regexpCapture("(.+)j.*", 1).toFloat() } /** Gets the value of this constant as a floating point value */ - float getValue() { - result = value - } + float getValue() { result = value } - override string toString() { - result = "ImaginaryLiteral" - } + override string toString() { result = "ImaginaryLiteral" } override Object getLiteralObject() { - py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN()) + py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN()) } override boolean booleanValue() { @@ -521,210 +409,154 @@ class ImaginaryLiteral extends Num { or this.getValue() != 0.0 and this.getValue() != -0.0 and result = true } - } class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr { - NegativeIntegerLiteral() { this.getOp() instanceof USub and this.getOperand() instanceof IntegerLiteral } - override boolean booleanValue() { - result = this.getOperand().(IntegerLiteral).booleanValue() - } + override boolean booleanValue() { result = this.getOperand().(IntegerLiteral).booleanValue() } override Object getLiteralObject() { - (py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) - and + (py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN()) } - /** + /** * Gets the (integer) value of this constant. Will not return a result if the value does not fit into - * a 32 bit signed value + * a 32 bit signed value */ - int getValue() { - result = -(this.getOperand().(IntegerLiteral).getValue()) - } - + int getValue() { result = -this.getOperand().(IntegerLiteral).getValue() } } -/** A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as - * "hello" are treated as Bytes for Python2, but Unicode for Python3. +/** + * A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as + * "hello" are treated as Bytes for Python2, but Unicode for Python3. */ class Unicode extends StrConst { - /* syntax: "hello" */ - - Unicode() { - this.isUnicode() - } + Unicode() { this.isUnicode() } override Object getLiteralObject() { py_cobjecttypes(result, theUnicodeType()) and py_cobjectnames(result, this.quotedString()) } - /** The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). + /** + * The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). * The following predicate help us match up a string/byte literals in the source * which the equivalent object. */ string quotedString() { - exists(string u_unquoted | - u_unquoted = this.getS() | - result = "u'" + u_unquoted + "'" - ) + exists(string u_unquoted | u_unquoted = this.getS() | result = "u'" + u_unquoted + "'") } - } - /* Compound Values */ - /** A dictionary expression, such as `{'key':'value'}` */ class Dict extends Dict_ { - /* syntax: {Expr: Expr, ...} */ - /** Gets the value of an item of this dict display */ - Expr getAValue() { - result = this.getAnItem().(DictDisplayItem).getValue() - } + Expr getAValue() { result = this.getAnItem().(DictDisplayItem).getValue() } - /** Gets the key of an item of this dict display, for those items that have keys + /** + * Gets the key of an item of this dict display, for those items that have keys * E.g, in {'a':1, **b} this returns only 'a' */ - Expr getAKey() { - result = this.getAnItem().(KeyValuePair).getKey() - } + Expr getAKey() { result = this.getAnItem().(KeyValuePair).getKey() } - override Expr getASubExpression() { - result = this.getAValue() or result = this.getAKey() - } - - override AstNode getAChildNode() { - result = this.getAnItem() - } + override Expr getASubExpression() { result = this.getAValue() or result = this.getAKey() } + override AstNode getAChildNode() { result = this.getAnItem() } } /** A list expression, such as `[ 1, 3, 5, 7, 9 ]` */ class List extends List_ { - /* syntax: [Expr, ...] */ - - override Expr getASubExpression() { - result = this.getAnElt() - } - + override Expr getASubExpression() { result = this.getAnElt() } } /** A set expression such as `{ 1, 3, 5, 7, 9 }` */ class Set extends Set_ { - /* syntax: {Expr, ...} */ - - override Expr getASubExpression() { - result = this.getAnElt() - } - + override Expr getASubExpression() { result = this.getAnElt() } } class PlaceHolder extends PlaceHolder_ { + string getId() { result = this.getVariable().getId() } - string getId() { - result = this.getVariable().getId() - } + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override string toString() { - result = "$" + this.getId() - } + override string toString() { result = "$" + this.getId() } override NameNode getAFlowNode() { result = super.getAFlowNode() } } /** A tuple expression such as `( 1, 3, 5, 7, 9 )` */ class Tuple extends Tuple_ { - /* syntax: (Expr, ...) */ - - override Expr getASubExpression() { - result = this.getAnElt() - } - + override Expr getASubExpression() { result = this.getAnElt() } } -/** A (plain variable) name expression, such as `var`. +/** + * A (plain variable) name expression, such as `var`. * `None`, `True` and `False` are excluded. */ class Name extends Name_ { - /* syntax: name */ - - string getId() { - result = this.getVariable().getId() - } + string getId() { result = this.getVariable().getId() } /** Whether this expression is a definition */ predicate isDefinition() { - py_expr_contexts(_, 5, this) or + py_expr_contexts(_, 5, this) + or /* Treat Param as a definition (which it is) */ - py_expr_contexts(_, 4, this) or + py_expr_contexts(_, 4, this) + or /* The target in an augmented assignment is also a definition (and a use) */ exists(AugAssign aa | aa.getTarget() = this) } - /** Whether this expression defines variable `v` - * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. */ + /** + * Whether this expression defines variable `v` + * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. + */ override predicate defines(Variable v) { - this.isDefinition() - and + this.isDefinition() and v = this.getVariable() } /** Whether this expression is a deletion */ - predicate isDeletion() { - py_expr_contexts(_, 2, this) - } + predicate isDeletion() { py_expr_contexts(_, 2, this) } - /** Whether this expression deletes variable `v`. - * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. */ + /** + * Whether this expression deletes variable `v`. + * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. + */ predicate deletes(Variable v) { - this.isDeletion() - and + this.isDeletion() and v = this.getVariable() } /** Whether this expression is a use */ - predicate isUse() { - py_expr_contexts(_, 3, this) - } + predicate isUse() { py_expr_contexts(_, 3, this) } - /** Whether this expression is a use of variable `v` - * If doing dataflow, then consider using SsaVariable.getAUse() for more precision. */ + /** + * Whether this expression is a use of variable `v` + * If doing dataflow, then consider using SsaVariable.getAUse() for more precision. + */ predicate uses(Variable v) { - this.isUse() - and + this.isUse() and v = this.getVariable() } - override predicate isConstant() { - none() - } + override predicate isConstant() { none() } - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } - override string toString() { - result = this.getId() - } + override string toString() { result = this.getId() } override NameNode getAFlowNode() { result = super.getAFlowNode() } @@ -732,36 +564,28 @@ class Name extends Name_ { /* Artificial variable names in comprehensions all start with "." */ this.getId().charAt(0) = "." } - } class Filter extends Filter_ { - override Expr getASubExpression() { result = this.getFilter() or result = this.getValue() } - } - /** A slice. E.g `0:1` in the expression `x[0:1]` */ class Slice extends Slice_ { - override Expr getASubExpression() { result = this.getStart() or result = this.getStop() or result = this.getStep() } - } /** A string constant. */ class StrConst extends Str_, ImmutableLiteral { - /* syntax: "hello" */ - predicate isUnicode() { this.getPrefix().charAt(_) = "u" or @@ -769,31 +593,21 @@ class StrConst extends Str_, ImmutableLiteral { or not this.getPrefix().charAt(_) = "b" and major_version() = 3 or - not this.getPrefix().charAt(_) = "b" and this.getEnclosingModule().hasFromFuture("unicode_literals") + not this.getPrefix().charAt(_) = "b" and + this.getEnclosingModule().hasFromFuture("unicode_literals") } - override - string strValue() { - result = this.getS() - } + override string strValue() { result = this.getS() } - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } - override AstNode getAChildNode() { - result = this.getAnImplicitlyConcatenatedPart() - } + override AstNode getAChildNode() { result = this.getAnImplicitlyConcatenatedPart() } /** Gets the text of this str constant */ - string getText() { - result = this.getS() - } + string getText() { result = this.getS() } /** Whether this is a docstring */ - predicate isDocString() { - exists(Scope s | s.getDocString() = this) - } + predicate isDocString() { exists(Scope s | s.getDocString() = this) } override boolean booleanValue() { this.getText() = "" and result = false @@ -802,174 +616,103 @@ class StrConst extends Str_, ImmutableLiteral { } override Object getLiteralObject() { none() } - } private predicate name_consts(Name_ n, string id) { - exists(Variable v | - py_variables(v, n) and id = v.getId() | + exists(Variable v | py_variables(v, n) and id = v.getId() | id = "True" or id = "False" or id = "None" ) } /** A named constant, one of `None`, `True` or `False` */ abstract class NameConstant extends Name, ImmutableLiteral { + NameConstant() { name_consts(this, _) } - NameConstant() { - name_consts(this, _) - } + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } + override string toString() { name_consts(this, result) } - override string toString() { - name_consts(this, result) - } - - override predicate isConstant() { - any() - } + override predicate isConstant() { any() } override NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() } - override predicate isArtificial() { - none() - } - + override predicate isArtificial() { none() } } /** A boolean named constant, either `True` or `False` */ -abstract class BooleanLiteral extends NameConstant { - -} +abstract class BooleanLiteral extends NameConstant { } /** The boolean named constant `True` */ class True extends BooleanLiteral { - /* syntax: True */ + True() { name_consts(this, "True") } - True() { - name_consts(this, "True") - } - - override Object getLiteralObject() { - name_consts(this, "True") and result = theTrueObject() - } - - override boolean booleanValue() { - result = true - } + override Object getLiteralObject() { name_consts(this, "True") and result = theTrueObject() } + override boolean booleanValue() { result = true } } /** The boolean named constant `False` */ class False extends BooleanLiteral { - /* syntax: False */ + False() { name_consts(this, "False") } - False() { - name_consts(this, "False") - } - - override Object getLiteralObject() { - name_consts(this, "False") and result = theFalseObject() - } - - override boolean booleanValue() { - result = false - } + override Object getLiteralObject() { name_consts(this, "False") and result = theFalseObject() } + override boolean booleanValue() { result = false } } /** `None` */ class None extends NameConstant { - /* syntax: None */ + None() { name_consts(this, "None") } - None() { - name_consts(this, "None") - } + override Object getLiteralObject() { name_consts(this, "None") and result = theNoneObject() } - override Object getLiteralObject() { - name_consts(this, "None") and result = theNoneObject() - } - - override boolean booleanValue() { - result = false - } + override boolean booleanValue() { result = false } } /** An await expression such as `await coro`. */ class Await extends Await_ { - /* syntax: await Expr */ - - override Expr getASubExpression() { - result = this.getValue() - } - + override Expr getASubExpression() { result = this.getValue() } } /** A formatted string literal expression, such as `f'hello {world!s}'` */ class Fstring extends Fstring_ { - /* syntax: f"Yes!" */ - - override Expr getASubExpression() { - result = this.getAValue() - } - + override Expr getASubExpression() { result = this.getAValue() } } -/** A formatted value (within a formatted string literal). +/** + * A formatted value (within a formatted string literal). * For example, in the string `f'hello {world!s}'` the formatted value is `world!s`. */ class FormattedValue extends FormattedValue_ { - override Expr getASubExpression() { result = this.getValue() or result = this.getFormatSpec() } - - } /* Expression Contexts */ - /** A context in which an expression used */ -class ExprContext extends ExprContext_ { - -} +class ExprContext extends ExprContext_ { } /** Load context, the context of var in len(var) */ -class Load extends Load_ { - -} +class Load extends Load_ { } /** Store context, the context of var in var = 0 */ -class Store extends Store_ { - -} +class Store extends Store_ { } /** Delete context, the context of var in del var */ -class Del extends Del_ { - -} +class Del extends Del_ { } /** This is an artifact of the Python grammar which includes an AugLoad context, even though it is never used. */ -library class AugLoad extends AugLoad_ { - -} +library class AugLoad extends AugLoad_ { } /** Augmented store context, the context of var in var += 1 */ -class AugStore extends AugStore_ { - -} +class AugStore extends AugStore_ { } /** Parameter context, the context of var in def f(var): pass */ -class Param extends Param_ { - -} - - +class Param extends Param_ { } diff --git a/python/ql/src/semmle/python/Files.qll b/python/ql/src/semmle/python/Files.qll index 461279c50e2..77f146d13cb 100644 --- a/python/ql/src/semmle/python/Files.qll +++ b/python/ql/src/semmle/python/Files.qll @@ -1,22 +1,14 @@ - import python /** A file */ class File extends Container { - - File() { - files(this, _, _, _, _) - } + File() { files(this, _, _, _, _) } /** DEPRECATED: Use `getAbsolutePath` instead. */ - deprecated override string getName() { - result = this.getAbsolutePath() - } + deprecated override string getName() { result = this.getAbsolutePath() } /** DEPRECATED: Use `getAbsolutePath` instead. */ - deprecated string getFullName() { - result = this.getAbsolutePath() - } + deprecated string getFullName() { result = this.getAbsolutePath() } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0 @@ -30,8 +22,7 @@ class File extends Container { /** Gets a short name for this file (just the file name) */ string getShortName() { - exists(string simple, string ext | files(this, _, simple, ext, _) | - result = simple + ext) + exists(string simple, string ext | files(this, _, simple, ext, _) | result = simple + ext) } private int lastLine() { @@ -40,27 +31,21 @@ class File extends Container { /** Whether line n is empty (it contains neither code nor comment). */ predicate emptyLine(int n) { - n in [0..this.lastLine()] - and + n in [0 .. this.lastLine()] and not occupied_line(this, n) } string getSpecifiedEncoding() { - exists(Comment c, Location l | - l = c.getLocation() and l.getFile() = this | + exists(Comment c, Location l | l = c.getLocation() and l.getFile() = this | l.getStartLine() < 3 and result = c.getText().regexpCapture(".*coding[:=]\\s*([-\\w.]+).*", 1) ) } - override string getAbsolutePath() { - files(this, result, _, _, _) - } + override string getAbsolutePath() { files(this, result, _, _, _) } /** Gets the URL of this file. */ - override string getURL() { - result = "file://" + this.getAbsolutePath() + ":0:0:0:0" - } + override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } override Container getImportRoot(int n) { /* File stem must be a legal Python identifier */ @@ -68,56 +53,40 @@ class File extends Container { result = this.getParent().getImportRoot(n) } - /** Gets the contents of this file as a string. + /** + * Gets the contents of this file as a string. * This will only work for those non-python files that * are specified to be extracted. */ - string getContents() { - file_contents(this, result) - } - + string getContents() { file_contents(this, result) } } private predicate occupied_line(File f, int n) { - exists(Location l | - l.getFile() = f | + exists(Location l | l.getFile() = f | l.getStartLine() = n or - exists(StrConst s | s.getLocation() = l | - n in [l.getStartLine() .. l.getEndLine()] - ) - ) + exists(StrConst s | s.getLocation() = l | n in [l.getStartLine() .. l.getEndLine()]) + ) } /** A folder (directory) */ class Folder extends Container { - - Folder() { - folders(this, _, _) - } + Folder() { folders(this, _, _) } /** DEPRECATED: Use `getAbsolutePath` instead. */ - deprecated override string getName() { - result = this.getAbsolutePath() - } + deprecated override string getName() { result = this.getAbsolutePath() } /** DEPRECATED: Use `getBaseName` instead. */ - deprecated string getSimple() { - folders(this, _, result) - } + deprecated string getSimple() { folders(this, _, result) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0 } - override string getAbsolutePath() { - folders(this, result, _) - } + override string getAbsolutePath() { folders(this, result, _) } /** Gets the URL of this folder. */ - override string getURL() { - result = "folder://" + this.getAbsolutePath() - } + override string getURL() { result = "folder://" + this.getAbsolutePath() } override Container getImportRoot(int n) { this.isImportRoot(n) and result = this @@ -126,32 +95,24 @@ class Folder extends Container { this.getBaseName().regexpMatch("[^\\d\\W]\\w*") and result = this.getParent().getImportRoot(n) } - } -/** +/** * A container is an abstract representation of a file system object that can - * hold elements of interest. + * hold elements of interest. */ abstract class Container extends @container { - - Container getParent() { - containerparent(result, this) - } + Container getParent() { containerparent(result, this) } /** Gets a child of this container */ - deprecated Container getChild() { - containerparent(this, result) - } + deprecated Container getChild() { containerparent(this, result) } /** * Gets a textual representation of the path of this container. * * This is the absolute path of the container. */ - string toString() { - result = this.getAbsolutePath() - } + string toString() { result = this.getAbsolutePath() } /** Gets the name of this container */ abstract string getName(); @@ -165,8 +126,9 @@ abstract class Container extends @container { * if the root folder is not a reflexive, transitive parent of this container. */ string getRelativePath() { - exists (string absPath, string pref | - absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) | + exists(string absPath, string pref | + absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) + | absPath = pref and result = "" or absPath = pref.regexpReplaceAll("/$", "") + "/" + result and @@ -175,36 +137,28 @@ abstract class Container extends @container { } /** Whether this file or folder is part of the standard library */ - predicate inStdlib() { - this.inStdlib(_, _) - } + predicate inStdlib() { this.inStdlib(_, _) } - /** Whether this file or folder is part of the standard library + /** + * Whether this file or folder is part of the standard library * for version `major.minor` */ predicate inStdlib(int major, int minor) { exists(Module m | - m.getPath() = this and + m.getPath() = this and m.inStdLib(major, minor) ) } /* Standard cross-language API */ - /** Gets a file or sub-folder in this container. */ - Container getAChildContainer() { - containerparent(this, result) - } + Container getAChildContainer() { containerparent(this, result) } /** Gets a file in this container. */ - File getAFile() { - result = this.getAChildContainer() - } + File getAFile() { result = this.getAChildContainer() } /** Gets a sub-folder in this container. */ - Folder getAFolder() { - result = this.getAChildContainer() - } + Folder getAFolder() { result = this.getAChildContainer() } /** * Gets the absolute, canonical path of this container, using forward slashes @@ -276,9 +230,7 @@ abstract class Container extends @container { * "/tmp/x.tar.gz""gz" * */ - string getExtension() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) - } + string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -297,9 +249,7 @@ abstract class Container extends @container { * "/tmp/x.tar.gz""x.tar" * */ - string getStem() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) - } + string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } File getFile(string baseName) { result = this.getAFile() and @@ -311,9 +261,7 @@ abstract class Container extends @container { result.getBaseName() = baseName } - Container getParentContainer() { - this = result.getAChildContainer() - } + Container getParentContainer() { this = result.getAChildContainer() } Container getChildContainer(string baseName) { result = this.getAChildContainer() and @@ -328,32 +276,31 @@ abstract class Container extends @container { abstract string getURL(); /** Holds if this folder is on the import path. */ - predicate isImportRoot() { - this.isImportRoot(_) - } + predicate isImportRoot() { this.isImportRoot(_) } - /** Holds if this folder is on the import path, at index `n` in the list of + /** + * Holds if this folder is on the import path, at index `n` in the list of * paths. The list of paths is composed of the paths passed to the extractor and - * `sys.path`. */ - predicate isImportRoot(int n) { - this.getName() = import_path_element(n) - } + * `sys.path`. + */ + predicate isImportRoot(int n) { this.getName() = import_path_element(n) } /** Holds if this folder is the root folder for the standard library. */ predicate isStdLibRoot(int major, int minor) { - major = major_version() and minor = minor_version() and + major = major_version() and + minor = minor_version() and this.isStdLibRoot() } /** Holds if this folder is the root folder for the standard library. */ predicate isStdLibRoot() { - /* Look for a standard lib module and find its import path + /* + * Look for a standard lib module and find its import path * We use `os` as it is the most likely to be imported and * `tty` because it is small for testing. */ - exists(Module m | - m.getName() = "os" or m.getName() = "tty" - | + + exists(Module m | m.getName() = "os" or m.getName() = "tty" | m.getFile().getImportRoot() = this ) } @@ -371,7 +318,6 @@ abstract class Container extends @container { /** Gets the path element from which this container would be loaded, given the index into the list of possible paths `n`. */ abstract Container getImportRoot(int n); - } private string import_path_element(int n) { @@ -379,53 +325,46 @@ private string import_path_element(int n) { path = get_path("extractor.path") and k = 0 or path = get_path("sys.path") and k = count(get_path("extractor.path").splitAt(pathsep)) - | + | py_flags_versioned("os.pathsep", pathsep, _) and - result = path.splitAt(pathsep, n-k).replaceAll("\\", "/") + result = path.splitAt(pathsep, n - k).replaceAll("\\", "/") ) } -private string get_path(string name) { - py_flags_versioned(name, result, _) -} +private string get_path(string name) { py_flags_versioned(name, result, _) } class Location extends @location { - /** Gets the file for this location */ - File getFile() { - result = this.getPath() - } + File getFile() { result = this.getPath() } private Container getPath() { locations_default(this, result, _, _, _, _) or - exists(Module m | locations_ast(this, m, _, _, _, _) | - result = m.getPath() - ) + exists(Module m | locations_ast(this, m, _, _, _, _) | result = m.getPath()) } /** Gets the start line of this location */ int getStartLine() { - locations_default(this, _, result, _, _, _) - or locations_ast(this,_,result,_,_,_) + locations_default(this, _, result, _, _, _) or + locations_ast(this, _, result, _, _, _) } /** Gets the start column of this location */ int getStartColumn() { - locations_default(this, _, _, result, _, _) - or locations_ast(this, _, _, result, _, _) + locations_default(this, _, _, result, _, _) or + locations_ast(this, _, _, result, _, _) } /** Gets the end line of this location */ int getEndLine() { - locations_default(this, _, _, _, result, _) - or locations_ast(this, _, _, _, result, _) + locations_default(this, _, _, _, result, _) or + locations_ast(this, _, _, _, result, _) } /** Gets the end column of this location */ int getEndColumn() { - locations_default(this, _, _, _, _, result) - or locations_ast(this, _, _, _, _, result) + locations_default(this, _, _, _, _, result) or + locations_ast(this, _, _, _, _, result) } string toString() { @@ -436,20 +375,20 @@ class Location extends @location { exists(File f | f.getAbsolutePath() = filepath | locations_default(this, f, bl, bc, el, ec) or - exists(Module m | m.getFile() = f | - locations_ast(this, m, bl, bc, el, ec)) - ) + exists(Module m | m.getFile() = f | locations_ast(this, m, bl, bc, el, ec)) + ) } - } /** A non-empty line in the source code */ class Line extends @py_line { - predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { - exists(Module m | m.getFile().getAbsolutePath() = filepath and - el = bl and bc = 1 and - py_line_lengths(this, m, bl, ec)) + exists(Module m | + m.getFile().getAbsolutePath() = filepath and + el = bl and + bc = 1 and + py_line_lengths(this, m, bl, ec) + ) } string toString() { @@ -459,58 +398,37 @@ class Line extends @py_line { } /** Gets the line number of this line */ - int getLineNumber() { - py_line_lengths(this, _, result, _) - } + int getLineNumber() { py_line_lengths(this, _, result, _) } /** Gets the length of this line */ - int getLength() { - py_line_lengths(this, _, _, result) - } + int getLength() { py_line_lengths(this, _, _, result) } /** Gets the file for this line */ - Module getModule() { - py_line_lengths(this, result, _, _) - } - + Module getModule() { py_line_lengths(this, result, _, _) } } -/** +/** * A syntax error. Note that if there is a syntax error in a module, - * much information about that module will be lost + * much information about that module will be lost */ class SyntaxError extends Location { + SyntaxError() { py_syntax_error_versioned(this, _, major_version().toString()) } - SyntaxError() { - py_syntax_error_versioned(this, _, major_version().toString()) - } - - override string toString() { - result = "Syntax Error" - } + override string toString() { result = "Syntax Error" } /** Gets the message corresponding to this syntax error */ - string getMessage() { - py_syntax_error_versioned(this, result, major_version().toString()) - } - + string getMessage() { py_syntax_error_versioned(this, result, major_version().toString()) } } -/** +/** * An encoding error. Note that if there is an encoding error in a module, - * much information about that module will be lost + * much information about that module will be lost */ class EncodingError extends SyntaxError { - EncodingError() { /* Leave spaces around 'decode' in unlikely event it occurs as a name in a syntax error */ this.getMessage().toLowerCase().matches("% decode %") } - override string toString() { - result = "Encoding Error" - } - + override string toString() { result = "Encoding Error" } } - - diff --git a/python/ql/src/semmle/python/Flow.qll b/python/ql/src/semmle/python/Flow.qll index 15d10694714..e92db18c3cf 100755 --- a/python/ql/src/semmle/python/Flow.qll +++ b/python/ql/src/semmle/python/Flow.qll @@ -1,7 +1,8 @@ import python private import semmle.python.pointsto.PointsTo -/* Note about matching parent and child nodes and CFG splitting: +/* + * Note about matching parent and child nodes and CFG splitting: * * As a result of CFG splitting a single AST node may have multiple CFG nodes. * Therefore, when matching CFG nodes to children, we need to make sure that @@ -11,7 +12,6 @@ private import semmle.python.pointsto.PointsTo * Vice versa for child nodes that precede the parent. */ - private predicate augstore(ControlFlowNode load, ControlFlowNode store) { exists(Expr load_store | exists(AugAssign aa | aa.getTarget() = load_store) | toAst(load) = load_store and @@ -21,16 +21,14 @@ private predicate augstore(ControlFlowNode load, ControlFlowNode store) { } /** A non-dispatched getNode() to avoid negative recursion issues */ -private AstNode toAst(ControlFlowNode n) { - py_flow_bb_node(n, result, _, _) -} +private AstNode toAst(ControlFlowNode n) { py_flow_bb_node(n, result, _, _) } -/** A control flow node. Control flow nodes have a many-to-one relation with syntactic nodes, +/** + * A control flow node. Control flow nodes have a many-to-one relation with syntactic nodes, * although most syntactic nodes have only one corresponding control flow node. * Edges between control flow nodes include exceptional as well as normal control flow. */ class ControlFlowNode extends @py_flow_node { - /** Whether this control flow node is a load (including those in augmented assignments) */ predicate isLoad() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 3, e) and not augstore(_, this)) @@ -42,24 +40,16 @@ class ControlFlowNode extends @py_flow_node { } /** Whether this control flow node is a delete */ - predicate isDelete() { - exists(Expr e | e = toAst(this) | py_expr_contexts(_, 2, e)) - } + predicate isDelete() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 2, e)) } /** Whether this control flow node is a parameter */ - predicate isParameter() { - exists(Expr e | e = toAst(this) | py_expr_contexts(_, 4, e)) - } + predicate isParameter() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 4, e)) } /** Whether this control flow node is a store in an augmented assignment */ - predicate isAugStore() { - augstore(_, this) - } + predicate isAugStore() { augstore(_, this) } /** Whether this control flow node is a load in an augmented assignment */ - predicate isAugLoad() { - augstore(this, _) - } + predicate isAugLoad() { augstore(this, _) } /** Whether this flow node corresponds to a literal */ predicate isLiteral() { @@ -93,200 +83,141 @@ class ControlFlowNode extends @py_flow_node { } /** Use NameNode.isLoad() instead */ - deprecated predicate isUse() { - toAst(this) instanceof Name and this.isLoad() - } + deprecated predicate isUse() { toAst(this) instanceof Name and this.isLoad() } /** Use NameNode.isStore() */ - deprecated predicate isDefinition() { - toAst(this) instanceof Name and this.isStore() - } + deprecated predicate isDefinition() { toAst(this) instanceof Name and this.isStore() } /** Whether this flow node corresponds to an attribute expression */ - predicate isAttribute() { - toAst(this) instanceof Attribute - } + predicate isAttribute() { toAst(this) instanceof Attribute } /** Use AttrNode.isLoad() instead */ - deprecated predicate isAttributeLoad() { - toAst(this) instanceof Attribute and this.isLoad() - } + deprecated predicate isAttributeLoad() { toAst(this) instanceof Attribute and this.isLoad() } /** Use AttrNode.isStore() instead */ - deprecated predicate isAttributeStore() { - toAst(this) instanceof Attribute and this.isStore() - } + deprecated predicate isAttributeStore() { toAst(this) instanceof Attribute and this.isStore() } /** Whether this flow node corresponds to an subscript expression */ - predicate isSubscript() { - toAst(this) instanceof Subscript - } + predicate isSubscript() { toAst(this) instanceof Subscript } /** Use SubscriptNode.isLoad() instead */ - deprecated predicate isSubscriptLoad() { - toAst(this) instanceof Subscript and this.isLoad() - } + deprecated predicate isSubscriptLoad() { toAst(this) instanceof Subscript and this.isLoad() } /** Use SubscriptNode.isStore() instead */ - deprecated predicate isSubscriptStore() { - toAst(this) instanceof Subscript and this.isStore() - } + deprecated predicate isSubscriptStore() { toAst(this) instanceof Subscript and this.isStore() } /** Whether this flow node corresponds to an import member */ - predicate isImportMember() { - toAst(this) instanceof ImportMember - } + predicate isImportMember() { toAst(this) instanceof ImportMember } /** Whether this flow node corresponds to a call */ - predicate isCall() { - toAst(this) instanceof Call - } + predicate isCall() { toAst(this) instanceof Call } /** Whether this flow node is the first in a module */ - predicate isModuleEntry() { - this.isEntryNode() and toAst(this) instanceof Module - } + predicate isModuleEntry() { this.isEntryNode() and toAst(this) instanceof Module } /** Whether this flow node corresponds to an import */ - predicate isImport() { - toAst(this) instanceof ImportExpr - } + predicate isImport() { toAst(this) instanceof ImportExpr } /** Whether this flow node corresponds to a conditional expression */ - predicate isIfExp() { - toAst(this) instanceof IfExp - } + predicate isIfExp() { toAst(this) instanceof IfExp } /** Whether this flow node corresponds to a function definition expression */ - predicate isFunction() { - toAst(this) instanceof FunctionExpr - } + predicate isFunction() { toAst(this) instanceof FunctionExpr } /** Whether this flow node corresponds to a class definition expression */ - predicate isClass() { - toAst(this) instanceof ClassExpr - } + predicate isClass() { toAst(this) instanceof ClassExpr } /** Gets a predecessor of this flow node */ - ControlFlowNode getAPredecessor() { - this = result.getASuccessor() - } + ControlFlowNode getAPredecessor() { this = result.getASuccessor() } /** Gets a successor of this flow node */ - ControlFlowNode getASuccessor() { - py_successors(this, result) - } + ControlFlowNode getASuccessor() { py_successors(this, result) } /** Gets the immediate dominator of this flow node */ - ControlFlowNode getImmediateDominator() { - py_idoms(this, result) - } + ControlFlowNode getImmediateDominator() { py_idoms(this, result) } /** Gets the syntactic element corresponding to this flow node */ - AstNode getNode() { - py_flow_bb_node(this, result, _, _) - } + AstNode getNode() { py_flow_bb_node(this, result, _, _) } string toString() { - exists(Scope s | s.getEntryNode() = this | - result = "Entry node for " + s.toString() - ) + exists(Scope s | s.getEntryNode() = this | result = "Entry node for " + s.toString()) or - exists(Scope s | s.getANormalExit() = this | - result = "Exit node for " + s.toString() - ) + exists(Scope s | s.getANormalExit() = this | result = "Exit node for " + s.toString()) or not exists(Scope s | s.getEntryNode() = this or s.getANormalExit() = this) and result = "ControlFlowNode for " + this.getNode().toString() } /** Gets the location of this ControlFlowNode */ - Location getLocation() { - result = this.getNode().getLocation() - } + Location getLocation() { result = this.getNode().getLocation() } /** Whether this flow node is the first in its scope */ - predicate isEntryNode() { - py_scope_flow(this, _, -1) - } + predicate isEntryNode() { py_scope_flow(this, _, -1) } /** The value that this ControlFlowNode points-to. */ - predicate pointsTo(Value value) { - this.pointsTo(_, value, _) - } + predicate pointsTo(Value value) { this.pointsTo(_, value, _) } /** Gets the value that this ControlFlowNode points-to. */ - Value pointsTo() { - this.pointsTo(_, result, _) - } + Value pointsTo() { this.pointsTo(_, result, _) } /** Gets a value that this ControlFlowNode may points-to. */ - Value inferredValue() { - this.pointsTo(_, result, _) - } + Value inferredValue() { this.pointsTo(_, result, _) } /** The value and origin that this ControlFlowNode points-to. */ - predicate pointsTo(Value value, ControlFlowNode origin) { - this.pointsTo(_, value, origin) - } + predicate pointsTo(Value value, ControlFlowNode origin) { this.pointsTo(_, value, origin) } /** The value and origin that this ControlFlowNode points-to, given the context. */ predicate pointsTo(Context context, Value value, ControlFlowNode origin) { PointsTo::pointsTo(this, context, value, origin) } - /** + /** * Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly * precise, but may not provide information for a significant number of flow-nodes. * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. */ - pragma [nomagic] + pragma[nomagic] predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) { this.refersTo(_, obj, cls, origin) } /** Gets what this expression might "refer-to" in the given `context`. */ - pragma [nomagic] + pragma[nomagic] predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) { not obj = unknownValue() and not cls = theUnknownType() and PointsTo::points_to(this, context, obj, cls, origin) } - /** Whether this flow node might "refer-to" to `value` which is from `origin` + /** + * Whether this flow node might "refer-to" to `value` which is from `origin` * Unlike `this.refersTo(value, _, origin)` this predicate includes results * where the class cannot be inferred. */ - pragma [nomagic] + pragma[nomagic] predicate refersTo(Object obj, ControlFlowNode origin) { not obj = unknownValue() and PointsTo::points_to(this, _, obj, _, origin) } /** Equivalent to `this.refersTo(value, _)` */ - predicate refersTo(Object obj) { - this.refersTo(obj, _) - } + predicate refersTo(Object obj) { this.refersTo(obj, _) } /** Gets the basic block containing this flow node */ - BasicBlock getBasicBlock() { - result.contains(this) - } + BasicBlock getBasicBlock() { result.contains(this) } /** Gets the scope containing this flow node */ Scope getScope() { - if this.getNode() instanceof Scope then - /* Entry or exit node */ - result = this.getNode() - else - result = this.getNode().getScope() + if this.getNode() instanceof Scope + then + /* Entry or exit node */ + result = this.getNode() + else result = this.getNode().getScope() } /** Gets the enclosing module */ - Module getEnclosingModule() { - result = this.getScope().getEnclosingModule() - } + Module getEnclosingModule() { result = this.getScope().getEnclosingModule() } /** Gets a successor for this node if the relevant condition is True. */ ControlFlowNode getATrueSuccessor() { @@ -308,19 +239,15 @@ class ControlFlowNode extends @py_flow_node { /** Gets a successor for this node if no exception is raised. */ ControlFlowNode getANormalSuccessor() { - result = this.getASuccessor() and not - py_exception_successors(this, result) + result = this.getASuccessor() and + not py_exception_successors(this, result) } /** Whether the scope may be exited as a result of this node raising an exception */ - predicate isExceptionalExit(Scope s) { - py_scope_flow(this, s, 1) - } + predicate isExceptionalExit(Scope s) { py_scope_flow(this, s, 1) } /** Whether this node is a normal (non-exceptional) exit */ - predicate isNormalExit() { - py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) - } + predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) } /** Whether it is unlikely that this ControlFlowNode can be reached */ predicate unlikelyReachable() { @@ -340,93 +267,81 @@ class ControlFlowNode extends @py_flow_node { ) } - /** Check whether this control-flow node has complete points-to information. + /** + * Check whether this control-flow node has complete points-to information. * This would mean that the analysis managed to infer an over approximation * of possible values at runtime. */ predicate hasCompletePointsToSet() { - ( - // If the tracking failed, then `this` will be its own "origin". In that - // case, we want to exclude nodes for which there is also a different - // origin, as that would indicate that some paths failed and some did not. - this.refersTo(_, _, this) and - not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other)) - ) or ( - // If `this` is a use of a variable, then we must have complete points-to - // for that variable. - exists(SsaVariable v | v.getAUse() = this | - varHasCompletePointsToSet(v) - ) - ) + // If the tracking failed, then `this` will be its own "origin". In that + // case, we want to exclude nodes for which there is also a different + // origin, as that would indicate that some paths failed and some did not. + this.refersTo(_, _, this) and + not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other)) + or + // If `this` is a use of a variable, then we must have complete points-to + // for that variable. + exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v)) } /** Whether this strictly dominates other. */ - pragma [inline] predicate strictlyDominates(ControlFlowNode other) { + pragma[inline] + predicate strictlyDominates(ControlFlowNode other) { // This predicate is gigantic, so it must be inlined. // About 1.4 billion tuples for OpenStack Cinder. this.getBasicBlock().strictlyDominates(other.getBasicBlock()) or - exists(BasicBlock b, int i, int j | - this = b.getNode(i) and other = b.getNode(j) and i < j - ) + exists(BasicBlock b, int i, int j | this = b.getNode(i) and other = b.getNode(j) and i < j) } - /** Whether this dominates other. + /** + * Whether this dominates other. * Note that all nodes dominate themselves. */ - pragma [inline] predicate dominates(ControlFlowNode other) { + pragma[inline] + predicate dominates(ControlFlowNode other) { // This predicate is gigantic, so it must be inlined. this.getBasicBlock().strictlyDominates(other.getBasicBlock()) or - exists(BasicBlock b, int i, int j | - this = b.getNode(i) and other = b.getNode(j) and i <= j - ) + exists(BasicBlock b, int i, int j | this = b.getNode(i) and other = b.getNode(j) and i <= j) } /** Whether this strictly reaches other. */ - pragma [inline] predicate strictlyReaches(ControlFlowNode other) { + pragma[inline] + predicate strictlyReaches(ControlFlowNode other) { // This predicate is gigantic, even larger than strictlyDominates, // so it must be inlined. this.getBasicBlock().strictlyReaches(other.getBasicBlock()) or - exists(BasicBlock b, int i, int j | - this = b.getNode(i) and other = b.getNode(j) and i < j - ) + exists(BasicBlock b, int i, int j | this = b.getNode(i) and other = b.getNode(j) and i < j) } /* Holds if this CFG node is a branch */ - predicate isBranch() { - py_true_successors(this, _) or py_false_successors(this, _) - } + predicate isBranch() { py_true_successors(this, _) or py_false_successors(this, _) } - ControlFlowNode getAChild() { - result = this.getExprChild(this.getBasicBlock()) - } + ControlFlowNode getAChild() { result = this.getExprChild(this.getBasicBlock()) } /* join-ordering helper for `getAChild() */ - pragma [noinline] + pragma[noinline] private ControlFlowNode getExprChild(BasicBlock dom) { this.getNode().(Expr).getAChildNode() = result.getNode() and result.getBasicBlock().dominates(dom) and not this instanceof UnaryExprNode } - } - -/* This class exists to provide an implementation over ControlFlowNode.getNode() +/* + * This class exists to provide an implementation over ControlFlowNode.getNode() * that subsumes all the others in an way that's obvious to the optimiser. * This avoids wasting time on the trivial overrides on the ControlFlowNode subclasses. */ -private class AnyNode extends ControlFlowNode { - override AstNode getNode() { - result = super.getNode() - } +private class AnyNode extends ControlFlowNode { + override AstNode getNode() { result = super.getNode() } } - -/** Check whether a SSA variable has complete points-to information. +/** + * Check whether a SSA variable has complete points-to information. * This would mean that the analysis managed to infer an overapproximation * of possible values at runtime. */ @@ -449,28 +364,35 @@ private predicate varHasCompletePointsToSet(SsaVariable var) { /** A control flow node corresponding to a call expression, such as `func(...)` */ class CallNode extends ControlFlowNode { - - CallNode() { - toAst(this) instanceof Call - } + CallNode() { toAst(this) instanceof Call } /** Gets the flow node corresponding to the function expression for the call corresponding to this flow node */ ControlFlowNode getFunction() { - exists(Call c | this.getNode() = c and c.getFunc() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Call c | + this.getNode() = c and + c.getFunc() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the flow node corresponding to the nth argument of the call corresponding to this flow node */ ControlFlowNode getArg(int n) { - exists(Call c | this.getNode() = c and c.getArg(n) = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Call c | + this.getNode() = c and + c.getArg(n) = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the flow node corresponding to the named argument of the call corresponding to this flow node */ ControlFlowNode getArgByName(string name) { - exists(Call c, Keyword k | this.getNode() = c and k = c.getAKeyword() and - k.getValue() = result.getNode() and k.getArg() = name and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Call c, Keyword k | + this.getNode() = c and + k = c.getAKeyword() and + k.getValue() = result.getNode() and + k.getArg() = name and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the flow node corresponding to an argument of the call corresponding to this flow node */ @@ -489,15 +411,11 @@ class CallNode extends ControlFlowNode { } predicate isClassDecoratorCall() { - exists(ClassExpr cls | - this.getNode() = cls.getADecoratorCall() - ) + exists(ClassExpr cls | this.getNode() = cls.getADecoratorCall()) } predicate isFunctionDecoratorCall() { - exists(FunctionExpr func | - this.getNode() = func.getADecoratorCall() - ) + exists(FunctionExpr func | this.getNode() = func.getADecoratorCall()) } /** Gets the tuple (*) argument of this call, provided there is exactly one. */ @@ -505,60 +423,56 @@ class CallNode extends ControlFlowNode { result.getNode() = this.getNode().getStarArg() and result.getBasicBlock().dominates(this.getBasicBlock()) } - } /** A control flow corresponding to an attribute expression, such as `value.attr` */ class AttrNode extends ControlFlowNode { - AttrNode() { - toAst(this) instanceof Attribute - } + AttrNode() { toAst(this) instanceof Attribute } /** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node */ ControlFlowNode getObject() { - exists(Attribute a | this.getNode() = a and a.getObject() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Attribute a | + this.getNode() = a and + a.getObject() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Use getObject() instead */ - deprecated ControlFlowNode getValue() { - result = this.getObject() - } + deprecated ControlFlowNode getValue() { result = this.getObject() } /** Use getObject(name) instead */ - deprecated ControlFlowNode getValue(string name) { - result = this.getObject(name) - } + deprecated ControlFlowNode getValue(string name) { result = this.getObject(name) } - /** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node, - * with the matching name */ + /** + * Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node, + * with the matching name + */ ControlFlowNode getObject(string name) { exists(Attribute a | - this.getNode() = a and a.getObject() = result.getNode() and + this.getNode() = a and + a.getObject() = result.getNode() and a.getName() = name and - result.getBasicBlock().dominates(this.getBasicBlock())) + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the attribute name of the attribute expression corresponding to this flow node */ - string getName() { - exists(Attribute a | this.getNode() = a and a.getName() = result) - } + string getName() { exists(Attribute a | this.getNode() = a and a.getName() = result) } override Attribute getNode() { result = super.getNode() } - } /** A control flow node corresponding to a `from ... import ...` expression */ class ImportMemberNode extends ControlFlowNode { - ImportMemberNode() { - toAst(this) instanceof ImportMember - } + ImportMemberNode() { toAst(this) instanceof ImportMember } - /** Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node, - * with the matching name */ + /** + * Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node, + * with the matching name + */ ControlFlowNode getModule(string name) { - exists(ImportMember i | - this.getNode() = i and i.getModule() = result.getNode() | + exists(ImportMember i | this.getNode() = i and i.getModule() = result.getNode() | i.getName() = name and result.getBasicBlock().dominates(this.getBasicBlock()) ) @@ -567,60 +481,59 @@ class ImportMemberNode extends ControlFlowNode { override ImportMember getNode() { result = super.getNode() } } - /** A control flow node corresponding to an artificial expression representing an import */ class ImportExprNode extends ControlFlowNode { - - ImportExprNode() { - toAst(this) instanceof ImportExpr - } + ImportExprNode() { toAst(this) instanceof ImportExpr } override ImportExpr getNode() { result = super.getNode() } - } /** A control flow node corresponding to a `from ... import *` statement */ class ImportStarNode extends ControlFlowNode { - - ImportStarNode() { - toAst(this) instanceof ImportStar - } + ImportStarNode() { toAst(this) instanceof ImportStar } /** Gets the flow node corresponding to the module in the import-star corresponding to this flow node */ ControlFlowNode getModule() { - exists(ImportStar i | - this.getNode() = i and i.getModuleExpr() = result.getNode() | + exists(ImportStar i | this.getNode() = i and i.getModuleExpr() = result.getNode() | result.getBasicBlock().dominates(this.getBasicBlock()) ) } override ImportStar getNode() { result = super.getNode() } - } /** A control flow node corresponding to a subscript expression, such as `value[slice]` */ class SubscriptNode extends ControlFlowNode { - SubscriptNode() { - toAst(this) instanceof Subscript - } + SubscriptNode() { toAst(this) instanceof Subscript } - /** DEPRECATED: Use `getObject()` instead. - * This will be formally deprecated before the end 2018 and removed in 2019.*/ + /** + * DEPRECATED: Use `getObject()` instead. + * This will be formally deprecated before the end 2018 and removed in 2019. + */ deprecated ControlFlowNode getValue() { - exists(Subscript s | this.getNode() = s and s.getObject() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Subscript s | + this.getNode() = s and + s.getObject() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** flow node corresponding to the value of the sequence in a subscript operation */ ControlFlowNode getObject() { - exists(Subscript s | this.getNode() = s and s.getObject() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Subscript s | + this.getNode() = s and + s.getObject() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** flow node corresponding to the index in a subscript operation */ ControlFlowNode getIndex() { - exists(Subscript s | this.getNode() = s and s.getIndex() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Subscript s | + this.getNode() = s and + s.getIndex() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } override Subscript getNode() { result = super.getNode() } @@ -628,17 +541,18 @@ class SubscriptNode extends ControlFlowNode { /** A control flow node corresponding to a comparison operation, such as `x DeletionNode -> NameNode('b') -> AttrNode('y') -> DeletionNode`. */ class DeletionNode extends ControlFlowNode { - - DeletionNode() { - toAst(this) instanceof Delete - } + DeletionNode() { toAst(this) instanceof Delete } /** Gets the unique target of this deletion node. */ - ControlFlowNode getTarget() { - result.getASuccessor() = this - } - + ControlFlowNode getTarget() { result.getASuccessor() = this } } /** A control flow node corresponding to a sequence (tuple or list) literal */ @@ -806,20 +703,15 @@ abstract class SequenceNode extends ControlFlowNode { } /** Gets the control flow node for an element of this sequence */ - ControlFlowNode getAnElement() { - result = this.getElement(_) - } + ControlFlowNode getAnElement() { result = this.getElement(_) } /** Gets the control flow node for the nth element of this sequence */ abstract ControlFlowNode getElement(int n); - } /** A control flow node corresponding to a tuple expression such as `( 1, 3, 5, 7, 9 )` */ class TupleNode extends SequenceNode { - TupleNode() { - toAst(this) instanceof Tuple - } + TupleNode() { toAst(this) instanceof Tuple } override ControlFlowNode getElement(int n) { exists(Tuple t | this.getNode() = t and result.getNode() = t.getElt(n)) and @@ -833,9 +725,7 @@ class TupleNode extends SequenceNode { /** A control flow node corresponding to a list expression, such as `[ 1, 3, 5, 7, 9 ]` */ class ListNode extends SequenceNode { - ListNode() { - toAst(this) instanceof List - } + ListNode() { toAst(this) instanceof List } override ControlFlowNode getElement(int n) { exists(List l | this.getNode() = l and result.getNode() = l.getElt(n)) and @@ -845,14 +735,10 @@ class ListNode extends SequenceNode { this.getBasicBlock().dominates(result.getBasicBlock()) ) } - } class SetNode extends ControlFlowNode { - - SetNode() { - toAst(this) instanceof Set - } + SetNode() { toAst(this) instanceof Set } ControlFlowNode getAnElement() { exists(Set s | this.getNode() = s and result.getNode() = s.getElt(_)) and @@ -862,17 +748,14 @@ class SetNode extends ControlFlowNode { this.getBasicBlock().dominates(result.getBasicBlock()) ) } - } /** A control flow node corresponding to a dictionary literal, such as `{ 'a': 1, 'b': 2 }` */ class DictNode extends ControlFlowNode { + DictNode() { toAst(this) instanceof Dict } - DictNode() { - toAst(this) instanceof Dict - } - - /** Gets a key of this dictionary literal node, for those items that have keys + /** + * Gets a key of this dictionary literal node, for those items that have keys * E.g, in {'a':1, **b} this returns only 'a' */ ControlFlowNode getAKey() { @@ -880,12 +763,11 @@ class DictNode extends ControlFlowNode { result.getBasicBlock().dominates(this.getBasicBlock()) } - /** Gets a value of this dictionary literal node*/ + /** Gets a value of this dictionary literal node */ ControlFlowNode getAValue() { exists(Dict d | this.getNode() = d and result.getNode() = d.getAValue()) and result.getBasicBlock().dominates(this.getBasicBlock()) } - } private AstNode assigned_value(Expr lhs) { @@ -898,30 +780,31 @@ private AstNode assigned_value(Expr lhs) { /* lhs += x => result = (lhs + x) */ exists(AugAssign a, BinaryExpr b | b = a.getOperation() and result = b and lhs = b.getLeft()) or - /* ..., lhs, ... = ..., result, ... + /* + * ..., lhs, ... = ..., result, ... * or * ..., (..., lhs, ...), ... = ..., (..., result, ...), ... - */ + */ + exists(Assign a | nested_sequence_assign(a.getATarget(), a.getValue(), lhs, result)) or /* for lhs in seq: => `result` is the `for` node, representing the `iter(next(seq))` operation. */ result.(For).getTarget() = lhs } -predicate nested_sequence_assign(Expr left_parent, Expr right_parent, - Expr left_result, Expr right_result) { +predicate nested_sequence_assign( + Expr left_parent, Expr right_parent, Expr left_result, Expr right_result +) { exists(Assign a | a.getATarget().getASubExpression*() = left_parent and a.getValue().getASubExpression*() = right_parent ) and - exists(int i, Expr left_elem, Expr right_elem - | + exists(int i, Expr left_elem, Expr right_elem | ( left_elem = left_parent.(Tuple).getElt(i) or left_elem = left_parent.(List).getElt(i) - ) - and + ) and ( right_elem = right_parent.(Tuple).getElt(i) or @@ -936,10 +819,7 @@ predicate nested_sequence_assign(Expr left_parent, Expr right_parent, /** A flow node for a `for` statement. */ class ForNode extends ControlFlowNode { - - ForNode() { - toAst(this) instanceof For - } + ForNode() { toAst(this) instanceof For } override For getNode() { result = super.getNode() } @@ -954,7 +834,8 @@ class ForNode extends ControlFlowNode { ControlFlowNode getSequence() { exists(For for | toAst(this) = for and - for.getIter() = result.getNode() | + for.getIter() = result.getNode() + | result.getBasicBlock().dominates(this.getBasicBlock()) ) } @@ -974,15 +855,11 @@ class ForNode extends ControlFlowNode { toAst(this) = toAst(result) and this.getBasicBlock().dominates(result.getBasicBlock()) } - } /** A flow node for a `raise` statement */ class RaiseStmtNode extends ControlFlowNode { - - RaiseStmtNode() { - toAst(this) instanceof Raise - } + RaiseStmtNode() { toAst(this) instanceof Raise } /** Gets the control flow node for the exception raised by this raise statement */ ControlFlowNode getException() { @@ -992,14 +869,13 @@ class RaiseStmtNode extends ControlFlowNode { result.getBasicBlock().dominates(this.getBasicBlock()) ) } - } -/** A control flow node corresponding to a (plain variable) name expression, such as `var`. +/** + * A control flow node corresponding to a (plain variable) name expression, such as `var`. * `None`, `True` and `False` are excluded. */ class NameNode extends ControlFlowNode { - NameNode() { exists(Name n | py_flow_bb_node(this, n, _, _)) or @@ -1008,20 +884,21 @@ class NameNode extends ControlFlowNode { /** Whether this flow node defines the variable `v`. */ predicate defines(Variable v) { - exists(Name d | this.getNode() = d and d.defines(v)) - and not this.isLoad() + exists(Name d | this.getNode() = d and d.defines(v)) and + not this.isLoad() } /** Whether this flow node deletes the variable `v`. */ - predicate deletes(Variable v) { - exists(Name d | this.getNode() = d and d.deletes(v)) - } + predicate deletes(Variable v) { exists(Name d | this.getNode() = d and d.deletes(v)) } /** Whether this flow node uses the variable `v`. */ predicate uses(Variable v) { - this.isLoad() and exists(Name u | this.getNode() = u and u.uses(v)) + this.isLoad() and + exists(Name u | this.getNode() = u and u.uses(v)) or - exists(PlaceHolder u | this.getNode() = u and u.getVariable() = v and u.getCtx() instanceof Load) + exists(PlaceHolder u | + this.getNode() = u and u.getVariable() = v and u.getCtx() instanceof Load + ) or Scopes::use_of_global_variable(this, v.getScope(), v.getId()) } @@ -1033,58 +910,40 @@ class NameNode extends ControlFlowNode { } /** Whether this is a use of a local variable. */ - predicate isLocal() { - Scopes::local(this) - } + predicate isLocal() { Scopes::local(this) } /** Whether this is a use of a non-local variable. */ - predicate isNonLocal() { - Scopes::non_local(this) - } + predicate isNonLocal() { Scopes::non_local(this) } /** Whether this is a use of a global (including builtin) variable. */ - predicate isGlobal() { - Scopes::use_of_global_variable(this, _, _) - } - - predicate isSelf() { - exists(SsaVariable selfvar | - selfvar.isSelf() and selfvar.getAUse() = this - ) - } + predicate isGlobal() { Scopes::use_of_global_variable(this, _, _) } + predicate isSelf() { exists(SsaVariable selfvar | selfvar.isSelf() and selfvar.getAUse() = this) } } /** A control flow node corresponding to a named constant, one of `None`, `True` or `False`. */ class NameConstantNode extends NameNode { + NameConstantNode() { exists(NameConstant n | py_flow_bb_node(this, n, _, _)) } - NameConstantNode() { - exists(NameConstant n | py_flow_bb_node(this, n, _, _)) - } + deprecated override predicate defines(Variable v) { none() } - override deprecated predicate defines(Variable v) { none() } - - override deprecated predicate deletes(Variable v) { none() } - - /* We ought to override uses as well, but that has + deprecated override predicate deletes(Variable v) { none() } + /* + * We ought to override uses as well, but that has * a serious performance impact. - deprecated predicate uses(Variable v) { none() } - */ -} + * deprecated predicate uses(Variable v) { none() } + */ + + } /** A control flow node correspoinding to a starred expression, `*a`. */ class StarredNode extends ControlFlowNode { - StarredNode() { - toAst(this) instanceof Starred - } + StarredNode() { toAst(this) instanceof Starred } - ControlFlowNode getValue() { - toAst(result) = toAst(this).(Starred).getValue() - } + ControlFlowNode getValue() { toAst(result) = toAst(this).(Starred).getValue() } } private module Scopes { - private predicate fast_local(NameNode n) { exists(FastLocalVariable v | n.uses(v) and @@ -1110,29 +969,24 @@ private module Scopes { } // magic is fine, but we get questionable join-ordering of it - pragma [nomagic] + pragma[nomagic] predicate use_of_global_variable(NameNode n, Module scope, string name) { n.isLoad() and - not non_local(n) - and - not exists(SsaVariable var | - var.getAUse() = n | - var.getVariable() instanceof FastLocalVariable + not non_local(n) and + not exists(SsaVariable var | var.getAUse() = n | + var.getVariable() instanceof FastLocalVariable or n.getScope() instanceof Class and not maybe_undefined(var) - ) - and name = n.getId() - and scope = n.getEnclosingModule() + ) and + name = n.getId() and + scope = n.getEnclosingModule() } private predicate maybe_defined(SsaVariable var) { exists(var.getDefinition()) and not py_ssa_phi(var, _) and not var.getDefinition().isDelete() or - exists(SsaVariable input | - input = var.getAPhiInput() | - maybe_defined(input) - ) + exists(SsaVariable input | input = var.getAPhiInput() | maybe_defined(input)) } private predicate maybe_undefined(SsaVariable var) { @@ -1143,61 +997,52 @@ private module Scopes { maybe_undefined(var.getAPhiInput()) or exists(BasicBlock incoming | - exists(var.getAPhiInput()) and + exists(var.getAPhiInput()) and incoming.getASuccessor() = var.getDefinition().getBasicBlock() and not var.getAPhiInput().getDefinition().getBasicBlock().dominates(incoming) ) } - } /** A basic block (ignoring exceptional flow edges to scope exit) */ class BasicBlock extends @py_flow_node { - - BasicBlock() { - py_flow_bb_node(_, _, this, _) - } + BasicBlock() { py_flow_bb_node(_, _, this, _) } /** Whether this basic block contains the specified node */ - predicate contains(ControlFlowNode node) { - py_flow_bb_node(node, _, this, _) - } + predicate contains(ControlFlowNode node) { py_flow_bb_node(node, _, this, _) } /** Gets the nth node in this basic block */ - ControlFlowNode getNode(int n) { - py_flow_bb_node(result, _, this, n) - } + ControlFlowNode getNode(int n) { py_flow_bb_node(result, _, this, n) } - string toString() { - result = "BasicBlock" - } + string toString() { result = "BasicBlock" } /** Whether this basic block strictly dominates the other */ - pragma[nomagic] predicate strictlyDominates(BasicBlock other) { - other.getImmediateDominator+() = this - } + pragma[nomagic] + predicate strictlyDominates(BasicBlock other) { other.getImmediateDominator+() = this } /** Whether this basic block dominates the other */ - pragma[nomagic] predicate dominates(BasicBlock other) { + pragma[nomagic] + predicate dominates(BasicBlock other) { this = other or this.strictlyDominates(other) } - cached BasicBlock getImmediateDominator() { + cached + BasicBlock getImmediateDominator() { this.firstNode().getImmediateDominator().getBasicBlock() = result } - /** Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor - * of `other` but does not strictly dominate `other` */ + /** + * Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor + * of `other` but does not strictly dominate `other` + */ pragma[noinline] predicate dominanceFrontier(BasicBlock other) { this.dominates(other.getAPredecessor()) and not this.strictlyDominates(other) } - private ControlFlowNode firstNode() { - result = this - } + private ControlFlowNode firstNode() { result = this } /** Gets the last node in this basic block */ ControlFlowNode getLastNode() { @@ -1207,33 +1052,25 @@ class BasicBlock extends @py_flow_node { ) } - private predicate oneNodeBlock() { - this.firstNode() = this.getLastNode() - } + private predicate oneNodeBlock() { this.firstNode() = this.getLastNode() } private predicate startLocationInfo(string file, int line, int col) { - if this.firstNode().getNode() instanceof Scope then - this.firstNode().getASuccessor().getLocation().hasLocationInfo(file, line, col, _, _) - else - this.firstNode().getLocation().hasLocationInfo(file, line, col, _, _) + if this.firstNode().getNode() instanceof Scope + then this.firstNode().getASuccessor().getLocation().hasLocationInfo(file, line, col, _, _) + else this.firstNode().getLocation().hasLocationInfo(file, line, col, _, _) } private predicate endLocationInfo(int endl, int endc) { - if (this.getLastNode().getNode() instanceof Scope and not this.oneNodeBlock()) then - this.getLastNode().getAPredecessor().getLocation().hasLocationInfo(_, _, _, endl, endc) - else - this.getLastNode().getLocation().hasLocationInfo(_, _, _, endl, endc) + if this.getLastNode().getNode() instanceof Scope and not this.oneNodeBlock() + then this.getLastNode().getAPredecessor().getLocation().hasLocationInfo(_, _, _, endl, endc) + else this.getLastNode().getLocation().hasLocationInfo(_, _, _, endl, endc) } /** Gets a successor to this basic block */ - BasicBlock getASuccessor() { - result = this.getLastNode().getASuccessor().getBasicBlock() - } + BasicBlock getASuccessor() { result = this.getLastNode().getASuccessor().getBasicBlock() } /** Gets a predecessor to this basic block */ - BasicBlock getAPredecessor() { - result.getASuccessor() = this - } + BasicBlock getAPredecessor() { result.getASuccessor() = this } /** Whether flow from this basic block reaches a normal exit from its scope */ predicate reachesExit() { @@ -1243,15 +1080,12 @@ class BasicBlock extends @py_flow_node { } predicate hasLocationInfo(string file, int line, int col, int endl, int endc) { - this.startLocationInfo(file, line, col) - and + this.startLocationInfo(file, line, col) and this.endLocationInfo(endl, endc) } /** Gets a true successor to this basic block */ - BasicBlock getATrueSuccessor() { - result = this.getLastNode().getATrueSuccessor().getBasicBlock() - } + BasicBlock getATrueSuccessor() { result = this.getLastNode().getATrueSuccessor().getBasicBlock() } /** Gets a false successor to this basic block */ BasicBlock getAFalseSuccessor() { @@ -1271,9 +1105,9 @@ class BasicBlock extends @py_flow_node { } /** Gets the scope of this block */ - pragma [nomagic] Scope getScope() { - exists(ControlFlowNode n | - n.getBasicBlock() = this | + pragma[nomagic] + Scope getScope() { + exists(ControlFlowNode n | n.getBasicBlock() = this | /* Take care not to use an entry or exit node as that node's scope will be the outer scope */ not py_scope_flow(n, _, -1) and not py_scope_flow(n, _, 0) and @@ -1284,7 +1118,8 @@ class BasicBlock extends @py_flow_node { ) } - /** Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. + /** + * Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. */ predicate unlikelySuccessor(BasicBlock succ) { this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode()) @@ -1293,22 +1128,18 @@ class BasicBlock extends @py_flow_node { } /** Holds if this basic block strictly reaches the other. Is the start of other reachable from the end of this. */ - predicate strictlyReaches(BasicBlock other) { - this.getASuccessor+() = other - } + predicate strictlyReaches(BasicBlock other) { this.getASuccessor+() = other } /** Holds if this basic block reaches the other. Is the start of other reachable from the end of this. */ - predicate reaches(BasicBlock other) { - this = other or this.strictlyReaches(other) - } + predicate reaches(BasicBlock other) { this = other or this.strictlyReaches(other) } - /** Whether (as inferred by type inference) this basic block is likely to be reachable. + /** + * Whether (as inferred by type inference) this basic block is likely to be reachable. */ - predicate likelyReachable() { - start_bb_likely_reachable(this) - } + predicate likelyReachable() { start_bb_likely_reachable(this) } - /** Gets the `ConditionBlock`, if any, that controls this block and + /** + * Gets the `ConditionBlock`, if any, that controls this block and * does not control any other `ConditionBlock`s that control this block. * That is the `ConditionBlock` that is closest dominator. */ @@ -1321,22 +1152,17 @@ class BasicBlock extends @py_flow_node { not result.(ConditionBlock).controls(this, _) } - /** Holds if flow from this BasicBlock always reaches `succ` + /** + * Holds if flow from this BasicBlock always reaches `succ` */ predicate alwaysReaches(BasicBlock succ) { succ = this or - strictcount(this.getASuccessor()) = 1 - and succ = this.getASuccessor() + strictcount(this.getASuccessor()) = 1 and + succ = this.getASuccessor() or - forex(BasicBlock immsucc | - immsucc = this.getASuccessor() - | - immsucc.alwaysReaches(succ) - ) - + forex(BasicBlock immsucc | immsucc = this.getASuccessor() | immsucc.alwaysReaches(succ)) } - } private predicate start_bb_likely_reachable(BasicBlock b) { @@ -1358,6 +1184,3 @@ private predicate end_bb_likely_reachable(BasicBlock b) { not p = b.getLastNode() ) } - - - diff --git a/python/ql/src/semmle/python/Function.qll b/python/ql/src/semmle/python/Function.qll index 832a9121176..3bf991b313e 100644 --- a/python/ql/src/semmle/python/Function.qll +++ b/python/ql/src/semmle/python/Function.qll @@ -1,43 +1,37 @@ import python -/** +/** * A function, independent of defaults and binding. - * It is the syntactic entity that is compiled to a code object. + * It is the syntactic entity that is compiled to a code object. */ class Function extends Function_, Scope, AstNode { - /** The expression defining this function */ - CallableExpr getDefinition() { - result = this.getParent() - } + CallableExpr getDefinition() { result = this.getParent() } - /** The scope in which this function occurs, will be a class for a method, - * another function for nested functions, generator expressions or comprehensions, - * or a module for a plain function. */ - override Scope getEnclosingScope() { - result = this.getParent().(Expr).getScope() - } + /** + * The scope in which this function occurs, will be a class for a method, + * another function for nested functions, generator expressions or comprehensions, + * or a module for a plain function. + */ + override Scope getEnclosingScope() { result = this.getParent().(Expr).getScope() } - override Scope getScope() { - result = this.getEnclosingScope() - } + override Scope getScope() { result = this.getEnclosingScope() } /** Whether this function is declared in a class */ - predicate isMethod() { - exists(Class cls | this.getEnclosingScope() = cls) - } + predicate isMethod() { exists(Class cls | this.getEnclosingScope() = cls) } /** Whether this is a special method, that is does its name have the form `__xxx__` (except `__init__`) */ predicate isSpecialMethod() { this.isMethod() and exists(string name | this.getName() = name | name.matches("\\_\\_%\\_\\_") and - name != "__init__") + name != "__init__" + ) } - /** + /** * Whether this function is a generator function, - * that is whether it contains a yield or yield-from expression + * that is whether it contains a yield or yield-from expression */ predicate isGenerator() { exists(Yield y | y.getScope() = this) @@ -46,88 +40,63 @@ class Function extends Function_, Scope, AstNode { } /** Whether this function is declared in a class and is named `__init__` */ - predicate isInitMethod() { - this.isMethod() and this.getName() = "__init__" - } + predicate isInitMethod() { this.isMethod() and this.getName() = "__init__" } /** Gets a decorator of this function */ - Expr getADecorator() { - result = ((FunctionExpr)this.getDefinition()).getADecorator() - } + Expr getADecorator() { result = this.getDefinition().(FunctionExpr).getADecorator() } /** Gets the name of the nth argument (for simple arguments) */ - string getArgName(int index) { - result = ((Name)this.getArg(index)).getId() - } + string getArgName(int index) { result = this.getArg(index).(Name).getId() } Parameter getArgByName(string name) { result = this.getAnArg() and result.(Name).getId() = name } - override Location getLocation() { - py_scope_location(result, this) - } + override Location getLocation() { py_scope_location(result, this) } - override string toString() { - result = "Function " + this.getName() - } + override string toString() { result = "Function " + this.getName() } /** Gets the statements forming the body of this function */ - override StmtList getBody() { - result = Function_.super.getBody() - } + override StmtList getBody() { result = Function_.super.getBody() } /** Gets the nth statement in the function */ - override Stmt getStmt(int index) { - result = Function_.super.getStmt(index) - } + override Stmt getStmt(int index) { result = Function_.super.getStmt(index) } /** Gets a statement in the function */ - override Stmt getAStmt() { - result = Function_.super.getAStmt() - } + override Stmt getAStmt() { result = Function_.super.getAStmt() } /** Gets the name used to define this function */ - override string getName() { - result = Function_.super.getName() - } + override string getName() { result = Function_.super.getName() } /** Gets the metrics for this function */ - FunctionMetrics getMetrics() { - result = this - } + FunctionMetrics getMetrics() { result = this } /** Gets the FunctionObject corresponding to this function */ - FunctionObject getFunctionObject() { - result.getOrigin() = this.getDefinition() - } + FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() } - /** Whether this function is a procedure, that is, it has no explicit return statement and always returns None. - * Note that generator and async functions are not procedures as they return generators and coroutines respectively. */ + /** + * Whether this function is a procedure, that is, it has no explicit return statement and always returns None. + * Note that generator and async functions are not procedures as they return generators and coroutines respectively. + */ predicate isProcedure() { - not exists(this.getReturnNode()) and exists(this.getFallthroughNode()) and not this.isGenerator() and not this.isAsync() + not exists(this.getReturnNode()) and + exists(this.getFallthroughNode()) and + not this.isGenerator() and + not this.isAsync() } /** Gets the number of positional parameters */ - int getPositionalParameterCount() { - result = count(this.getAnArg()) - } + int getPositionalParameterCount() { result = count(this.getAnArg()) } /** Gets the number of keyword-only parameters */ - int getKeywordOnlyParameterCount() { - result = count(this.getAKwonlyarg()) - } + int getKeywordOnlyParameterCount() { result = count(this.getAKwonlyarg()) } /** Whether this function accepts a variable number of arguments. That is, whether it has a starred (*arg) parameter. */ - predicate hasVarArg() { - exists(this.getVararg()) - } + predicate hasVarArg() { exists(this.getVararg()) } /** Whether this function accepts arbitrary keyword arguments. That is, whether it has a double-starred (**kwarg) parameter. */ - predicate hasKwArg() { - exists(this.getKwarg()) - } + predicate hasKwArg() { exists(this.getKwarg()) } override AstNode getAChildNode() { result = this.getAStmt() or @@ -136,7 +105,8 @@ class Function extends Function_, Scope, AstNode { result = this.getKwarg() } - /** Gets the qualified name for this function. + /** + * Gets the qualified name for this function. * Should return the same name as the `__qualname__` attribute on functions in Python 3. */ string getQualifiedName() { @@ -145,38 +115,30 @@ class Function extends Function_, Scope, AstNode { exists(string enclosing_name | enclosing_name = this.getEnclosingScope().(Function).getQualifiedName() or - enclosing_name = this.getEnclosingScope().(Class).getQualifiedName() | + enclosing_name = this.getEnclosingScope().(Class).getQualifiedName() + | result = enclosing_name + "." + this.getName() ) } /** Gets the nth keyword-only parameter of this function. */ - Name getKeywordOnlyArg(int n) { - result = Function_.super.getKwonlyarg(n) - } + Name getKeywordOnlyArg(int n) { result = Function_.super.getKwonlyarg(n) } /** Gets a keyword-only parameter of this function. */ - Name getAKeywordOnlyArg() { - result = this.getKeywordOnlyArg(_) - } + Name getAKeywordOnlyArg() { result = this.getKeywordOnlyArg(_) } override Scope getEvaluatingScope() { - major_version() = 2 and exists(Comp comp | comp.getFunction() = this | result = comp.getEvaluatingScope()) + major_version() = 2 and + exists(Comp comp | comp.getFunction() = this | result = comp.getEvaluatingScope()) or not exists(Comp comp | comp.getFunction() = this) and result = this - or + or major_version() = 3 and result = this } - override - predicate containsInScope(AstNode inner) { - Scope.super.containsInScope(inner) - } + override predicate containsInScope(AstNode inner) { Scope.super.containsInScope(inner) } - override - predicate contains(AstNode inner) { - Scope.super.contains(inner) - } + override predicate contains(AstNode inner) { Scope.super.contains(inner) } /** Gets a control flow node for a return value of this function */ ControlFlowNode getAReturnValueFlowNode() { @@ -185,48 +147,36 @@ class Function extends Function_, Scope, AstNode { ret.getValue() = result.getNode() ) } - } /** A def statement. Note that FunctionDef extends Assign as a function definition binds the newly created function */ class FunctionDef extends Assign { - /* syntax: def name(...): ... */ - FunctionDef() { /* This is an artificial assignment the rhs of which is a (possibly decorated) FunctionExpr */ exists(FunctionExpr f | this.getValue() = f or this.getValue() = f.getADecoratorCall()) } - override string toString() { - result = "FunctionDef" - } + override string toString() { result = "FunctionDef" } /** Gets the function for this statement */ Function getDefinedFunction() { exists(FunctionExpr func | this.containsInScope(func) and result = func.getInnerScope()) } - override Stmt getLastStatement() { - result = this.getDefinedFunction().getLastStatement() - } - + override Stmt getLastStatement() { result = this.getDefinedFunction().getLastStatement() } } class FastLocalsFunction extends Function { - /** A function that uses 'fast' locals, stored in the frame not in a dictionary. */ - FastLocalsFunction () { - not exists(ImportStar i | i.getScope() = this) - and + FastLocalsFunction() { + not exists(ImportStar i | i.getScope() = this) and not exists(Exec e | e.getScope() = this) } - } /** A parameter. Either a Tuple or a Name (always a Name for Python 3) */ class Parameter extends Parameter_ { - Parameter() { /* Parameter_ is just defined as a Name or Tuple, narrow to actual parameters */ exists(ParameterList pl | py_exprs(this, _, pl, _)) @@ -245,36 +195,29 @@ class Parameter extends Parameter_ { } /** Gets this parameter if it is a Name (not a Tuple) */ - Name asName() { - result = this - } + Name asName() { result = this } /** Gets this parameter if it is a Tuple (not a Name) */ - Tuple asTuple() { - result = this - } + Tuple asTuple() { result = this } /** Gets the expression for the default value of this parameter */ Expr getDefault() { - exists(Function f, int n, int c, int d, Arguments args | - args = f.getDefinition().getArgs() | + exists(Function f, int n, int c, int d, Arguments args | args = f.getDefinition().getArgs() | f.getArg(n) = this and c = count(f.getAnArg()) and d = count(args.getADefault()) and - result = args.getDefault(d-c+n) + result = args.getDefault(d - c + n) ) } /** Gets the annotation expression of this parameter */ Expr getAnnotation() { - exists(Function f, int n, Arguments args | - args = f.getDefinition().getArgs() | + exists(Function f, int n, Arguments args | args = f.getDefinition().getArgs() | f.getArg(n) = this and result = args.getAnnotation(n) ) or - exists(Function f, Arguments args | - args = f.getDefinition().getArgs() | + exists(Function f, Arguments args | args = f.getDefinition().getArgs() | f.getKwarg() = this and result = args.getKwargannotation() or @@ -283,21 +226,13 @@ class Parameter extends Parameter_ { ) } - Variable getVariable() { - result.getAnAccess() = this.asName() - } + Variable getVariable() { result.getAnAccess() = this.asName() } /** Gets the position of this parameter */ - int getPosition() { - exists(Function f | - f.getArg(result) = this - ) - } + int getPosition() { exists(Function f | f.getArg(result) = this) } /** Gets the name of this parameter */ - string getName() { - result = this.asName().getId() - } + string getName() { result = this.asName().getId() } /** Holds if this parameter is the first parameter of a method. It is not necessarily called "self" */ predicate isSelf() { @@ -307,45 +242,39 @@ class Parameter extends Parameter_ { ) } - /** Holds if this parameter is a 'varargs' parameter. + /** + * Holds if this parameter is a 'varargs' parameter. * The `varargs` in `f(a, b, *varargs)`. */ - predicate isVarargs() { - exists(Function func | func.getVararg() = this) - } + predicate isVarargs() { exists(Function func | func.getVararg() = this) } - /** Holds if this parameter is a 'kwargs' parameter. + /** + * Holds if this parameter is a 'kwargs' parameter. * The `kwargs` in `f(a, b, **kwargs)`. */ - predicate isKwargs() { - exists(Function func | func.getKwarg() = this) - } - + predicate isKwargs() { exists(Function func | func.getKwarg() = this) } } /** An expression that generates a callable object, either a function expression or a lambda */ abstract class CallableExpr extends Expr { - - /** Gets the parameters of this callable. - * This predicate is called getArgs(), rather than getParameters() for compatibility with Python's AST module. */ + /** + * Gets the parameters of this callable. + * This predicate is called getArgs(), rather than getParameters() for compatibility with Python's AST module. + */ abstract Arguments getArgs(); /** Gets the function scope of this code expression. */ abstract Function getInnerScope(); - } /** An (artificial) expression corresponding to a function definition. */ class FunctionExpr extends FunctionExpr_, CallableExpr { - override Expr getASubExpression() { result = this.getArgs().getASubExpression() or result = this.getReturns() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } Call getADecoratorCall() { result.getArg(0) = this or @@ -353,9 +282,7 @@ class FunctionExpr extends FunctionExpr_, CallableExpr { } /** Gets a decorator of this function expression */ - Expr getADecorator() { - result = this.getADecoratorCall().getFunc() - } + Expr getADecorator() { result = this.getADecoratorCall().getFunc() } override AstNode getAChildNode() { result = this.getASubExpression() @@ -363,47 +290,32 @@ class FunctionExpr extends FunctionExpr_, CallableExpr { result = this.getInnerScope() } - override Function getInnerScope() { - result = FunctionExpr_.super.getInnerScope() - } - - override Arguments getArgs() { - result = FunctionExpr_.super.getArgs() - } + override Function getInnerScope() { result = FunctionExpr_.super.getInnerScope() } + override Arguments getArgs() { result = FunctionExpr_.super.getArgs() } } -/** A lambda expression, such as lambda x:x*x */ +/** A lambda expression, such as lambda x:x*x */ class Lambda extends Lambda_, CallableExpr { - /** Gets the expression to the right of the colon in this lambda expression */ Expr getExpression() { - exists(Return ret | ret = this.getInnerScope().getStmt(0) | - result = ret.getValue()) + exists(Return ret | ret = this.getInnerScope().getStmt(0) | result = ret.getValue()) } - override Expr getASubExpression() { - result = this.getArgs().getASubExpression() - } + override Expr getASubExpression() { result = this.getArgs().getASubExpression() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getInnerScope() } - override Function getInnerScope() { - result = Lambda_.super.getInnerScope() - } - - override Arguments getArgs() { - result = Lambda_.super.getArgs() - } + override Function getInnerScope() { result = Lambda_.super.getInnerScope() } + override Arguments getArgs() { result = Lambda_.super.getArgs() } } /** The arguments in a function definition */ class Arguments extends Arguments_ { - Expr getASubExpression() { result = this.getAKwDefault() or result = this.getAnAnnotation() or @@ -412,5 +324,3 @@ class Arguments extends Arguments_ { result = this.getADefault() } } - - diff --git a/python/ql/src/semmle/python/GuardedControlFlow.qll b/python/ql/src/semmle/python/GuardedControlFlow.qll index b7caa192f51..0675f336828 100644 --- a/python/ql/src/semmle/python/GuardedControlFlow.qll +++ b/python/ql/src/semmle/python/GuardedControlFlow.qll @@ -2,9 +2,10 @@ import python /** A basic block which terminates in a condition, splitting the subsequent control flow */ class ConditionBlock extends BasicBlock { - ConditionBlock() { - exists(ControlFlowNode succ | succ = this.getATrueSuccessor() or succ = this.getAFalseSuccessor()) + exists(ControlFlowNode succ | + succ = this.getATrueSuccessor() or succ = this.getAFalseSuccessor() + ) } /** Basic blocks controlled by this condition, i.e. those BBs for which the condition is testIsTrue */ @@ -13,12 +14,12 @@ class ConditionBlock extends BasicBlock { * For this block to control the block 'controlled' with 'testIsTrue' the following must be true: * Execution must have passed through the test i.e. 'this' must strictly dominate 'controlled'. * Execution must have passed through the 'testIsTrue' edge leaving 'this'. - * + * * Although "passed through the true edge" implies that this.getATrueSuccessor() dominates 'controlled', * the reverse is not true, as flow may have passed through another edge to get to this.getATrueSuccessor() - * so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that + * so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that * all predecessors of this.getATrueSuccessor() are either this or dominated by this.getATrueSuccessor(). - * + * * For example, in the following python snippet: * * if x: @@ -26,7 +27,7 @@ class ConditionBlock extends BasicBlock { * false_successor * uncontrolled * - * false_successor dominates uncontrolled, but not all of its predecessors are this (if x) + * false_successor dominates uncontrolled, but not all of its predecessors are this (if x) * or dominated by itself. Whereas in the following code: * * if x: @@ -35,22 +36,21 @@ class ConditionBlock extends BasicBlock { * false_successor * uncontrolled * - * the block 'while controlled' is controlled because all of its predecessors are this (if x) + * the block 'while controlled' is controlled because all of its predecessors are this (if x) * or (in the case of 'also_controlled') dominated by itself. - * + * * The additional constraint on the predecessors of the test successor implies * that `this` strictly dominates `controlled` so that isn't necessary to check * directly. */ - exists(BasicBlock succ | + + exists(BasicBlock succ | testIsTrue = true and succ = this.getATrueSuccessor() or testIsTrue = false and succ = this.getAFalseSuccessor() - | - succ.dominates(controlled) and - forall(BasicBlock pred | pred.getASuccessor() = succ | - pred = this or succ.dominates(pred) - ) + | + succ.dominates(controlled) and + forall(BasicBlock pred | pred.getASuccessor() = succ | pred = this or succ.dominates(pred)) ) } @@ -58,11 +58,11 @@ class ConditionBlock extends BasicBlock { predicate controlsEdge(BasicBlock pred, BasicBlock succ, boolean testIsTrue) { this.controls(pred, testIsTrue) and succ = pred.getASuccessor() or - pred = this and ( + pred = this and + ( testIsTrue = true and succ = this.getATrueSuccessor() or testIsTrue = false and succ = this.getAFalseSuccessor() ) } - } diff --git a/python/ql/src/semmle/python/Import.qll b/python/ql/src/semmle/python/Import.qll index 1b9b2aed6f4..4e52d08dc68 100644 --- a/python/ql/src/semmle/python/Import.qll +++ b/python/ql/src/semmle/python/Import.qll @@ -1,14 +1,12 @@ import python private import semmle.python.types.Builtins -/** An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial; - * `import x` is transformed into `import x as x` */ +/** + * An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial; + * `import x` is transformed into `import x as x` + */ class Alias extends Alias_ { - - Location getLocation() { - result = this.getValue().getLocation() - } - + Location getLocation() { result = this.getValue().getLocation() } } private predicate valid_module_name(string name) { @@ -19,37 +17,34 @@ private predicate valid_module_name(string name) { /** An artificial expression representing an import */ class ImportExpr extends ImportExpr_ { - - private string basePackageName(int n) { n = 1 and result = this.getEnclosingModule().getPackageName() - or - exists(string bpnm1 | bpnm1 = this.basePackageName(n-1) and + or + exists(string bpnm1 | + bpnm1 = this.basePackageName(n - 1) and bpnm1.matches("%.%") and result = bpnm1.regexpReplaceAll("\\.[^.]*$", "") ) } private predicate implicitRelativeImportsAllowed() { - // relative imports are no longer allowed in Python 3 + // relative imports are no longer allowed in Python 3 major_version() < 3 and // and can be explicitly turned off in later versions of Python 2 not getEnclosingModule().hasFromFuture("absolute_import") } - /** The language specifies level as -1 if relative imports are to be tried first, 0 for absolute imports, - * and level > 0 for explicit relative imports. */ + /** + * The language specifies level as -1 if relative imports are to be tried first, 0 for absolute imports, + * and level > 0 for explicit relative imports. + */ override int getLevel() { exists(int l | l = super.getLevel() | l > 0 and result = l or /* The extractor may set level to 0 even though relative imports apply */ - l = 0 and ( - if this.implicitRelativeImportsAllowed() then - result = -1 - else - result = 0 - ) + l = 0 and + (if this.implicitRelativeImportsAllowed() then result = -1 else result = 0) ) } @@ -64,49 +59,47 @@ class ImportExpr extends ImportExpr_ { } private string qualifiedTopName() { - if (this.getLevel() <= 0) then ( - result = this.getTopName() - ) else ( + if this.getLevel() <= 0 + then result = this.getTopName() + else ( result = basePackageName(this.getLevel()) and valid_module_name(result) ) } - /** Gets the name by which the lowest level module or package is imported. - * NOTE: This is the name that used to import the module, - * which may not be the name of the module. */ + /** + * Gets the name by which the lowest level module or package is imported. + * NOTE: This is the name that used to import the module, + * which may not be the name of the module. + */ string bottomModuleName() { result = relativeTopName() + this.remainderOfName() or - ( - not exists(relativeTopName()) and - result = this.qualifiedTopName() + this.remainderOfName() - ) + not exists(relativeTopName()) and + result = this.qualifiedTopName() + this.remainderOfName() } /** Gets the name of topmost module or package being imported */ string topModuleName() { result = relativeTopName() or - ( - not exists(relativeTopName()) and - result = this.qualifiedTopName() - ) + not exists(relativeTopName()) and + result = this.qualifiedTopName() } - /** Gets the full name of the module resulting from evaluating this import. + /** + * Gets the full name of the module resulting from evaluating this import. * NOTE: This is the name that used to import the module, - * which may not be the name of the module. */ + * which may not be the name of the module. + */ string getImportedModuleName() { exists(string bottomName | bottomName = this.bottomModuleName() | - if this.isTop() then - result = topModuleName() - else - result = bottomName + if this.isTop() then result = topModuleName() else result = bottomName ) } - /** Gets the names of the modules that may be imported by this import. + /** + * Gets the names of the modules that may be imported by this import. * For example this predicate would return 'x' and 'x.y' for `import x.y` */ string getAnImportedModuleName() { @@ -115,26 +108,24 @@ class ImportExpr extends ImportExpr_ { result = this.getAnImportedModuleName().regexpReplaceAll("\\.[^.]*$", "") } - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } - private string getTopName() { - result = this.getName().regexpReplaceAll("\\..*", "") - } + private string getTopName() { result = this.getName().regexpReplaceAll("\\..*", "") } private string remainderOfName() { - not exists(this.getName()) and result = "" or - this.getLevel() <= 0 and result = this.getName().regexpReplaceAll("^[^\\.]*", "") or + not exists(this.getName()) and result = "" + or + this.getLevel() <= 0 and result = this.getName().regexpReplaceAll("^[^\\.]*", "") + or this.getLevel() > 0 and result = "." + this.getName() } - /** Whether this import is relative, that is not absolute. - * See https://www.python.org/dev/peps/pep-0328/ */ + /** + * Whether this import is relative, that is not absolute. + * See https://www.python.org/dev/peps/pep-0328/ + */ predicate isRelative() { /* Implicit */ exists(this.relativeTopName()) @@ -142,24 +133,22 @@ class ImportExpr extends ImportExpr_ { /* Explicit */ this.getLevel() > 0 } - } /** A `from ... import ...` expression */ class ImportMember extends ImportMember_ { - - override Expr getASubExpression() { - result = this.getModule() - } + override Expr getASubExpression() { result = this.getModule() } override predicate hasSideEffects() { /* Strictly this only has side-effects if the module is a package */ any() } - /** Gets the full name of the module resulting from evaluating this import. - * NOTE: This is the name that used to import the module, - * which may not be the name of the module. */ + /** + * Gets the full name of the module resulting from evaluating this import. + * NOTE: This is the name that used to import the module, + * which may not be the name of the module. + */ string getImportedModuleName() { result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName() } @@ -169,26 +158,22 @@ class ImportMember extends ImportMember_ { /** An import statement */ class Import extends Import_ { - /* syntax: import modname */ - private ImportExpr getAModuleExpr() { result = this.getAName().getValue() - or - result = ((ImportMember)this.getAName().getValue()).getModule() + or + result = this.getAName().getValue().(ImportMember).getModule() } - /** Use getAnImportedModuleName(), + /** + * Use getAnImportedModuleName(), * possibly combined with ModuleObject.importedAs() - * Gets a module imported by this import statement */ - deprecated Module getAModule() { - result.getName() = this.getAnImportedModuleName() - } + * Gets a module imported by this import statement + */ + deprecated Module getAModule() { result.getName() = this.getAnImportedModuleName() } /** Whether this a `from ... import ...` statement */ - predicate isFromImport() { - this.getAName().getValue() instanceof ImportMember - } + predicate isFromImport() { this.getAName().getValue() instanceof ImportMember } override Expr getASubExpression() { result = this.getAModuleExpr() or @@ -196,73 +181,61 @@ class Import extends Import_ { result = this.getAName().getValue() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } - /** Gets the name of an imported module. + /** + * Gets the name of an imported module. * For example, for the import statement `import bar` which * is a relative import in package "foo", this would return * "foo.bar". - * The import statment `from foo import bar` would return + * The import statment `from foo import bar` would return * `foo` and `foo.bar` - * */ + */ string getAnImportedModuleName() { result = this.getAModuleExpr().getAnImportedModuleName() or exists(ImportMember m, string modname | m = this.getAName().getValue() and - modname = m.getModule().(ImportExpr).getImportedModuleName() | + modname = m.getModule().(ImportExpr).getImportedModuleName() + | result = modname or result = modname + "." + m.getName() ) } - } /** An import * statement */ class ImportStar extends ImportStar_ { - /* syntax: from modname import * */ - ImportExpr getModuleExpr() { result = this.getModule() or - result = ((ImportMember)this.getModule()).getModule() + result = this.getModule().(ImportMember).getModule() } - override string toString() { - result = "from " + this.getModuleExpr().getName() + " import *" - } + override string toString() { result = "from " + this.getModuleExpr().getName() + " import *" } - /** Use getAnImportedModuleName(), + /** + * Use getAnImportedModuleName(), * possibly combined with ModuleObject.importedAs() - * Gets the module imported by this import * statement + * Gets the module imported by this import * statement */ - deprecated Module getTheModule() { - result.getName() = this.getImportedModuleName() - } + deprecated Module getTheModule() { result.getName() = this.getImportedModuleName() } - override Expr getASubExpression() { - result = this.getModule() - } + override Expr getASubExpression() { result = this.getModule() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } /** Gets the name of the imported module. */ - string getImportedModuleName() { - result = this.getModuleExpr().getImportedModuleName() - } - + string getImportedModuleName() { result = this.getModuleExpr().getImportedModuleName() } } -/** A statement that imports a module. This can be any statement that includes the `import` keyword, - * such as `import sys`, `from sys import version` or `from sys import *`. */ +/** + * A statement that imports a module. This can be any statement that includes the `import` keyword, + * such as `import sys`, `from sys import version` or `from sys import *`. + */ class ImportingStmt extends Stmt { - ImportingStmt() { this instanceof Import or @@ -271,9 +244,8 @@ class ImportingStmt extends Stmt { /** Gets the name of an imported module. */ string getAnImportedModuleName() { - result = this.(Import).getAnImportedModuleName() + result = this.(Import).getAnImportedModuleName() or result = this.(ImportStar).getImportedModuleName() } - } diff --git a/python/ql/src/semmle/python/Keywords.qll b/python/ql/src/semmle/python/Keywords.qll index 62fe40f95f7..7d8b687f83c 100644 --- a/python/ql/src/semmle/python/Keywords.qll +++ b/python/ql/src/semmle/python/Keywords.qll @@ -1,105 +1,60 @@ import python class KeyValuePair extends KeyValuePair_, DictDisplayItem { - /* syntax: Expr : Expr */ + override Location getLocation() { result = KeyValuePair_.super.getLocation() } - override Location getLocation() { - result = KeyValuePair_.super.getLocation() - } - - override string toString() { - result = KeyValuePair_.super.toString() - } + override string toString() { result = KeyValuePair_.super.toString() } /** Gets the value of this dictionary unpacking. */ - override Expr getValue() { - result = KeyValuePair_.super.getValue() - } + override Expr getValue() { result = KeyValuePair_.super.getValue() } - override Scope getScope() { - result = this.getValue().getScope() - } + override Scope getScope() { result = this.getValue().getScope() } override AstNode getAChildNode() { result = this.getKey() or result = this.getValue() } - } /** A double-starred expression in a call or dict literal. */ class DictUnpacking extends DictUnpacking_, DictUnpackingOrKeyword, DictDisplayItem { + override Location getLocation() { result = DictUnpacking_.super.getLocation() } - override Location getLocation() { - result = DictUnpacking_.super.getLocation() - } - - override string toString() { - result = DictUnpacking_.super.toString() - } + override string toString() { result = DictUnpacking_.super.toString() } /** Gets the value of this dictionary unpacking. */ - override Expr getValue() { - result = DictUnpacking_.super.getValue() - } + override Expr getValue() { result = DictUnpacking_.super.getValue() } - override Scope getScope() { - result = this.getValue().getScope() - } - - override AstNode getAChildNode() { - result = this.getValue() - } + override Scope getScope() { result = this.getValue().getScope() } + override AstNode getAChildNode() { result = this.getValue() } } abstract class DictUnpackingOrKeyword extends DictItem { - abstract Expr getValue(); - override string toString() { - result = "DictUnpackingOrKeyword with missing toString" - } - + override string toString() { result = "DictUnpackingOrKeyword with missing toString" } } abstract class DictDisplayItem extends DictItem { - abstract Expr getValue(); - override string toString() { - result = "DictDisplayItem with missing toString" - } - + override string toString() { result = "DictDisplayItem with missing toString" } } /** A keyword argument in a call. For example `arg=expr` in `foo(0, arg=expr)` */ -class Keyword extends Keyword_, DictUnpackingOrKeyword { - +class Keyword extends Keyword_, DictUnpackingOrKeyword { /* syntax: name = Expr */ + override Location getLocation() { result = Keyword_.super.getLocation() } - override Location getLocation() { - result = Keyword_.super.getLocation() - } - - override string toString() { - result = Keyword_.super.toString() - } + override string toString() { result = Keyword_.super.toString() } /** Gets the value of this keyword argument. */ - override Expr getValue() { - result = Keyword_.super.getValue() - } + override Expr getValue() { result = Keyword_.super.getValue() } - override Scope getScope() { - result = this.getValue().getScope() - } - - override AstNode getAChildNode() { - result = this.getValue() - } + override Scope getScope() { result = this.getValue().getScope() } + override AstNode getAChildNode() { result = this.getValue() } } - diff --git a/python/ql/src/semmle/python/Metrics.qll b/python/ql/src/semmle/python/Metrics.qll index 66d3179ef4e..694843600bd 100644 --- a/python/ql/src/semmle/python/Metrics.qll +++ b/python/ql/src/semmle/python/Metrics.qll @@ -2,29 +2,23 @@ import python /** The metrics for a function */ class FunctionMetrics extends Function { - - /** Gets the total number of lines (including blank lines) - * from the definition to the end of the function */ - int getNumberOfLines() { - py_alllines(this, result) - } + /** + * Gets the total number of lines (including blank lines) + * from the definition to the end of the function + */ + int getNumberOfLines() { py_alllines(this, result) } /** Gets the number of lines of code in the function */ - int getNumberOfLinesOfCode() { - py_codelines(this, result) - } + int getNumberOfLinesOfCode() { py_codelines(this, result) } /** Gets the number of lines of comments in the function */ - int getNumberOfLinesOfComments() { - py_commentlines(this, result) - } + int getNumberOfLinesOfComments() { py_commentlines(this, result) } /** Gets the number of lines of docstring in the function */ - int getNumberOfLinesOfDocStrings() { - py_docstringlines(this, result) - } + int getNumberOfLinesOfDocStrings() { py_docstringlines(this, result) } - /** Cyclomatic complexity: + /** + * Cyclomatic complexity: * The number of linearly independent paths through the source code. * Computed as E - N + 2P, * where @@ -34,14 +28,17 @@ class FunctionMetrics extends Function { */ int getCyclomaticComplexity() { exists(int E, int N | - N = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) - and - E = count(BasicBlock b1, BasicBlock b2 | - b1 = this.getABasicBlock() and b1.likelyReachable() and - b2 = this.getABasicBlock() and b2.likelyReachable() and - b2 = b1.getASuccessor() and not b1.unlikelySuccessor(b2) - ) - | + N = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) and + E = + count(BasicBlock b1, BasicBlock b2 | + b1 = this.getABasicBlock() and + b1.likelyReachable() and + b2 = this.getABasicBlock() and + b2.likelyReachable() and + b2 = b1.getASuccessor() and + not b1.unlikelySuccessor(b2) + ) + | result = E - N + 2 ) } @@ -51,24 +48,23 @@ class FunctionMetrics extends Function { or exists(BasicBlock mid | mid = this.getABasicBlock() and result = mid.getASuccessor()) } - - /** Dependency of Callables + + /** + * Dependency of Callables * One callable "this" depends on another callable "result" * if "this" makes some call to a method that may end up being "result". - */ + */ FunctionMetrics getADependency() { result != this and not non_coupling_method(result) and - exists(Call call | - call.getScope() = this | - exists(FunctionObject callee | - callee.getFunction() = result | + exists(Call call | call.getScope() = this | + exists(FunctionObject callee | callee.getFunction() = result | call.getAFlowNode().getFunction().refersTo(callee) ) or - exists(Attribute a | - call.getFunc() = a | - unique_root_method(result, a.getName()) or + exists(Attribute a | call.getFunc() = a | + unique_root_method(result, a.getName()) + or exists(Name n | a.getObject() = n and n.getId() = "self" | result.getScope() = this.getScope() and result.getName() = a.getName() @@ -76,145 +72,122 @@ class FunctionMetrics extends Function { ) ) } - - /** Afferent Coupling + + /** + * Afferent Coupling * the number of callables that depend on this method. * This is sometimes called the "fan-in" of a method. */ - int getAfferentCoupling() { - result = count(FunctionMetrics m | m.getADependency() = this ) - } - - /** Efferent Coupling + int getAfferentCoupling() { result = count(FunctionMetrics m | m.getADependency() = this) } + + /** + * Efferent Coupling * the number of methods that this method depends on * This is sometimes called the "fan-out" of a method. */ - int getEfferentCoupling() { - result = count(FunctionMetrics m | this.getADependency() = m) - } + int getEfferentCoupling() { result = count(FunctionMetrics m | this.getADependency() = m) } int getNumberOfParametersWithoutDefault() { - result = this.getPositionalParameterCount() - - count(((FunctionExpr)this.getDefinition()).getArgs().getADefault()) + result = + this.getPositionalParameterCount() - + count(this.getDefinition().(FunctionExpr).getArgs().getADefault()) } - - int getStatementNestingDepth() { - result = max(Stmt s | s.getScope() = this | getNestingDepth(s)) - } - - int getNumberOfCalls() { - result = count(Call c | c.getScope() = this) - } - + + int getStatementNestingDepth() { result = max(Stmt s | s.getScope() = this | getNestingDepth(s)) } + + int getNumberOfCalls() { result = count(Call c | c.getScope() = this) } } /** The metrics for a class */ class ClassMetrics extends Class { - - /** Gets the total number of lines (including blank lines) - * from the definition to the end of the class */ - int getNumberOfLines() { - py_alllines(this, result) - } + /** + * Gets the total number of lines (including blank lines) + * from the definition to the end of the class + */ + int getNumberOfLines() { py_alllines(this, result) } /** Gets the number of lines of code in the class */ - int getNumberOfLinesOfCode() { - py_codelines(this, result) - } + int getNumberOfLinesOfCode() { py_codelines(this, result) } /** Gets the number of lines of comments in the class */ - int getNumberOfLinesOfComments() { - py_commentlines(this, result) - } + int getNumberOfLinesOfComments() { py_commentlines(this, result) } /** Gets the number of lines of docstrings in the class */ - int getNumberOfLinesOfDocStrings() { - py_docstringlines(this, result) - } - + int getNumberOfLinesOfDocStrings() { py_docstringlines(this, result) } + private predicate dependsOn(Class other) { other != this and ( - exists(FunctionMetrics f1, FunctionMetrics f2 | - f1.getADependency() = f2 | + exists(FunctionMetrics f1, FunctionMetrics f2 | f1.getADependency() = f2 | f1.getScope() = this and f2.getScope() = other ) or - exists(Function f, Call c, ClassObject cls | - c.getScope() = f and f.getScope() = this | + exists(Function f, Call c, ClassObject cls | c.getScope() = f and f.getScope() = this | c.getFunc().refersTo(cls) and cls.getPyClass() = other ) ) } - - /** The afferent coupling of a class is the number of classes that - * directly depend on it. + + /** + * The afferent coupling of a class is the number of classes that + * directly depend on it. */ - int getAfferentCoupling() { - result = count(ClassMetrics t | t.dependsOn(this)) - } - - /** The efferent coupling of a class is the number of classes that + int getAfferentCoupling() { result = count(ClassMetrics t | t.dependsOn(this)) } + + /** + * The efferent coupling of a class is the number of classes that * it directly depends on. */ - int getEfferentCoupling() { - result = count(ClassMetrics t | this.dependsOn(t)) - } - + int getEfferentCoupling() { result = count(ClassMetrics t | this.dependsOn(t)) } + int getInheritanceDepth() { - exists(ClassObject cls | - cls.getPyClass() = this | - result = max(classInheritanceDepth(cls)) - ) + exists(ClassObject cls | cls.getPyClass() = this | result = max(classInheritanceDepth(cls))) } /* -------- CHIDAMBER AND KEMERER LACK OF COHESION IN METHODS ------------ */ - - /* The aim of this metric is to try and determine whether a class - * represents one abstraction (good) or multiple abstractions (bad). - * If a class represents multiple abstractions, it should be split - * up into multiple classes. - * - * In the Chidamber and Kemerer method, this is measured as follows: - * n1 = number of pairs of distinct methods in a class that do *not* - * have at least one commonly accessed field - * n2 = number of pairs of distinct methods in a class that do - * have at least one commonly accessed field - * lcom = ((n1 - n2)/2 max 0) - * + /* + * The aim of this metric is to try and determine whether a class + * represents one abstraction (good) or multiple abstractions (bad). + * If a class represents multiple abstractions, it should be split + * up into multiple classes. + * + * In the Chidamber and Kemerer method, this is measured as follows: + * n1 = number of pairs of distinct methods in a class that do *not* + * have at least one commonly accessed field + * n2 = number of pairs of distinct methods in a class that do + * have at least one commonly accessed field + * lcom = ((n1 - n2)/2 max 0) + * * We divide by 2 because each pair (m1,m2) is counted twice in n1 and n2. */ - + /** should function f be excluded from the cohesion computation? */ - predicate ignoreLackOfCohesion(Function f) { - f.isInitMethod() or f.isSpecialMethod() - } - + predicate ignoreLackOfCohesion(Function f) { f.isInitMethod() or f.isSpecialMethod() } + private predicate methodPair(Function m1, Function m2) { m1.getScope() = this and m2.getScope() = this and - not this.ignoreLackOfCohesion(m1) and + not this.ignoreLackOfCohesion(m1) and not this.ignoreLackOfCohesion(m2) and m1 != m2 } - + private predicate one_accesses_other(Function m1, Function m2) { this.methodPair(m1, m2) and ( - exists(SelfAttributeRead sa | - sa.getName() = m1.getName() and - sa.getScope() = m2 - ) - or - exists(SelfAttributeRead sa | - sa.getName() = m2.getName() and - sa.getScope() = m1 - ) + exists(SelfAttributeRead sa | + sa.getName() = m1.getName() and + sa.getScope() = m2 + ) + or + exists(SelfAttributeRead sa | + sa.getName() = m2.getName() and + sa.getScope() = m1 + ) ) } - - + /** do m1 and m2 access a common field or one calls the other? */ private predicate shareField(Function m1, Function m2) { this.methodPair(m1, m2) and @@ -222,142 +195,117 @@ class ClassMetrics extends Class { exists(SelfAttributeRead sa | sa.getName() = name and sa.getScope() = m1 - ) - and + ) and exists(SelfAttributeRead sa | sa.getName() = name and sa.getScope() = m2 ) ) } - + private int similarMethodPairs() { - result = count(Function m1, Function m2 | - this.methodPair(m1, m2) and - (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) - ) / 2 + result = + count(Function m1, Function m2 | + this.methodPair(m1, m2) and + (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) + ) / 2 } - + private int methodPairs() { - result = count(Function m1, Function m2 | this.methodPair(m1, m2)) / 2 + result = count(Function m1, Function m2 | this.methodPair(m1, m2)) / 2 } - + /** return Chidamber and Kemerer Lack of Cohesion */ int getLackOfCohesionCK() { exists(int n | - n = this.methodPairs() - 2 * this.similarMethodPairs() - and + n = this.methodPairs() - 2 * this.similarMethodPairs() and result = n.maximum(0) - ) - } - - private predicate similarMethodPairDag(Function m1, Function m2, int line) { - (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) and - line = m1.getLocation().getStartLine() and - line < m2.getLocation().getStartLine() - } - - private predicate subgraph(Function m, int line) { - this.similarMethodPairDag(m, _, line) and not this.similarMethodPairDag(_, m, _) - or - exists(Function other | this.subgraph(other, line) | - this.similarMethodPairDag(other, m, _) or - this.similarMethodPairDag(m, other, _) - ) - } - - predicate unionSubgraph(Function m, int line) { - line = min(int l | this.subgraph(m, l)) - } + ) + } - /** return Hitz and Montazeri Lack of Cohesion */ - int getLackOfCohesionHM() { - result = count(int line | - this.unionSubgraph(_, line) - ) - } - + private predicate similarMethodPairDag(Function m1, Function m2, int line) { + (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) and + line = m1.getLocation().getStartLine() and + line < m2.getLocation().getStartLine() + } + + private predicate subgraph(Function m, int line) { + this.similarMethodPairDag(m, _, line) and not this.similarMethodPairDag(_, m, _) + or + exists(Function other | this.subgraph(other, line) | + this.similarMethodPairDag(other, m, _) or + this.similarMethodPairDag(m, other, _) + ) + } + + predicate unionSubgraph(Function m, int line) { line = min(int l | this.subgraph(m, l)) } + + /** return Hitz and Montazeri Lack of Cohesion */ + int getLackOfCohesionHM() { result = count(int line | this.unionSubgraph(_, line)) } } private int classInheritanceDepth(ClassObject cls) { /* Prevent run-away recursion in case of circular inheritance */ - not cls.getASuperType() = cls - and + not cls.getASuperType() = cls and ( - exists(ClassObject sup | - cls.getABaseType() = sup | - result = classInheritanceDepth(sup) + 1 - ) - or - not exists(cls.getABaseType()) and ( - major_version() = 2 and result = 0 - or - major_version() > 2 and result = 1 - ) + exists(ClassObject sup | cls.getABaseType() = sup | result = classInheritanceDepth(sup) + 1) + or + not exists(cls.getABaseType()) and + ( + major_version() = 2 and result = 0 + or + major_version() > 2 and result = 1 + ) ) } class ModuleMetrics extends Module { - /** Gets the total number of lines (including blank lines) in the module */ - int getNumberOfLines() { - py_alllines(this, result) - } + int getNumberOfLines() { py_alllines(this, result) } - /** Gets the number of lines of code in the module */ - int getNumberOfLinesOfCode() { - py_codelines(this, result) - } + /** Gets the number of lines of code in the module */ + int getNumberOfLinesOfCode() { py_codelines(this, result) } /** Gets the number of lines of comments in the module */ - int getNumberOfLinesOfComments() { - py_commentlines(this, result) - } + int getNumberOfLinesOfComments() { py_commentlines(this, result) } /** Gets the number of lines of docstrings in the module */ - int getNumberOfLinesOfDocStrings() { - py_docstringlines(this, result) - } - - /** The afferent coupling of a class is the number of classes that - * directly depend on it. - */ - int getAfferentCoupling() { - result = count(ModuleMetrics t | t.dependsOn(this)) - } + int getNumberOfLinesOfDocStrings() { py_docstringlines(this, result) } - /** The efferent coupling of a class is the number of classes that + /** + * The afferent coupling of a class is the number of classes that + * directly depend on it. + */ + int getAfferentCoupling() { result = count(ModuleMetrics t | t.dependsOn(this)) } + + /** + * The efferent coupling of a class is the number of classes that * it directly depends on. */ - int getEfferentCoupling() { - result = count(ModuleMetrics t | this.dependsOn(t)) - } + int getEfferentCoupling() { result = count(ModuleMetrics t | this.dependsOn(t)) } private predicate dependsOn(Module other) { other != this and ( - exists(FunctionMetrics f1, FunctionMetrics f2 | - f1.getADependency() = f2 | + exists(FunctionMetrics f1, FunctionMetrics f2 | f1.getADependency() = f2 | f1.getEnclosingModule() = this and f2.getEnclosingModule() = other ) or - exists(Function f, Call c, ClassObject cls | - c.getScope() = f and f.getScope() = this | + exists(Function f, Call c, ClassObject cls | c.getScope() = f and f.getScope() = this | c.getFunc().refersTo(cls) and cls.getPyClass().getEnclosingModule() = other ) ) } - } /** Helpers for coupling */ - predicate unique_root_method(Function func, string name) { - name = func.getName() and - not exists(FunctionObject f, FunctionObject other | + name = func.getName() and + not exists(FunctionObject f, FunctionObject other | f.getFunction() = func and - other.getName() = name | + other.getName() = name + | not other.overrides(f) ) } @@ -375,13 +323,11 @@ predicate non_coupling_method(Function f) { private int getNestingDepth(Stmt s) { not exists(Stmt outer | outer.getASubStatement() = s) and result = 1 or - exists(Stmt outer | - outer.getASubStatement() = s | - if s.(If).isElif() or s instanceof ExceptStmt then + exists(Stmt outer | outer.getASubStatement() = s | + if s.(If).isElif() or s instanceof ExceptStmt + then /* If statement is an `elif` or `except` then it is not indented relative to its parent */ result = getNestingDepth(outer) - else - result = getNestingDepth(outer) + 1 + else result = getNestingDepth(outer) + 1 ) } - diff --git a/python/ql/src/semmle/python/Module.qll b/python/ql/src/semmle/python/Module.qll index 68361d1b12c..4d428636893 100644 --- a/python/ql/src/semmle/python/Module.qll +++ b/python/ql/src/semmle/python/Module.qll @@ -2,47 +2,42 @@ import python private import semmle.python.objects.ObjectAPI private import semmle.python.objects.Modules -/** A module. This is the top level element in an AST, corresponding to a source file. - * It is also a Scope; the scope of global variables. */ +/** + * A module. This is the top level element in an AST, corresponding to a source file. + * It is also a Scope; the scope of global variables. + */ class Module extends Module_, Scope, AstNode { - override string toString() { result = this.getKind() + " " + this.getName() or /* No name is defined, which means that this module is not on an import path. So it must be a script */ - not exists(this.getName()) and not this.isPackage() and + not exists(this.getName()) and + not this.isPackage() and result = "Script " + this.getFile().getShortName() or /* Package missing name, so just use the path instead */ - not exists(this.getName()) and this.isPackage() and - result = "Package at " + this.getPath().getAbsolutePath() + not exists(this.getName()) and + this.isPackage() and + result = "Package at " + this.getPath().getAbsolutePath() } - /** This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. - * The enclosing scope of this module (always none) */ - override Scope getScope() { - none() - } + /** + * This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. + * The enclosing scope of this module (always none) + */ + override Scope getScope() { none() } /** The enclosing scope of this module (always none) */ - override Scope getEnclosingScope() { - none() - } + override Scope getEnclosingScope() { none() } /** Gets the statements forming the body of this module */ - override StmtList getBody() { - result = Module_.super.getBody() - } + override StmtList getBody() { result = Module_.super.getBody() } /** Gets the nth statement of this module */ - override Stmt getStmt(int n) { - result = Module_.super.getStmt(n) - } + override Stmt getStmt(int n) { result = Module_.super.getStmt(n) } /** Gets a top-level statement in this module */ - override Stmt getAStmt() { - result = Module_.super.getAStmt() - } + override Stmt getAStmt() { result = Module_.super.getAStmt() } /** Gets the name of this module */ override string getName() { @@ -54,15 +49,13 @@ class Module extends Module_, Scope, AstNode { /** Gets the short name of the module. For example the short name of module x.y.z is 'z' */ string getShortName() { - result = this.getName().suffix(this.getPackage().getName().length()+1) + result = this.getName().suffix(this.getPackage().getName().length() + 1) or result = this.getName() and not exists(this.getPackage()) } /** Gets this module */ - override Module getEnclosingModule() { - result = this - } + override Module getEnclosingModule() { result = this } /** Gets the __init__ module of this module if the module is a package and it has an __init__ module */ Module getInitModule() { @@ -70,34 +63,25 @@ class Module extends Module_, Scope, AstNode { } /** Whether this module is a package initializer */ - predicate isPackageInit() { - this.getName().matches("%\\_\\_init\\_\\_") and not this.isPackage() - } + predicate isPackageInit() { this.getName().matches("%\\_\\_init\\_\\_") and not this.isPackage() } - /** Gets a name exported by this module, that is the names that will be added to a namespace by 'from this-module import *' */ + /** Gets a name exported by this module, that is the names that will be added to a namespace by 'from this-module import *' */ string getAnExport() { py_exports(this, result) or - exists(ModuleObjectInternal mod | - mod.getSource() = this.getEntryNode() | + exists(ModuleObjectInternal mod | mod.getSource() = this.getEntryNode() | mod.(ModuleValue).exports(result) ) } /** Gets the source file for this module */ - File getFile() { - py_module_path(this, result) - } + File getFile() { py_module_path(this, result) } /** Gets the source file or folder for this module or package */ - Container getPath() { - py_module_path(this, result) - } + Container getPath() { py_module_path(this, result) } /** Whether this is a package */ - predicate isPackage() { - this.getPath() instanceof Folder - } + predicate isPackage() { this.getPath() instanceof Folder } /** Gets the package containing this module (or parent package if this is a package) */ Module getPackage() { @@ -112,15 +96,13 @@ class Module extends Module_, Scope, AstNode { } /** Gets the metrics for this module */ - ModuleMetrics getMetrics() { - result = this - } + ModuleMetrics getMetrics() { result = this } - /** Use ModuleObject.getAnImportedModule() instead. - * Gets a module imported by this module */ - deprecated Module getAnImportedModule() { - result.getName() = this.getAnImportedModuleName() - } + /** + * Use ModuleObject.getAnImportedModule() instead. + * Gets a module imported by this module + */ + deprecated Module getAnImportedModule() { result.getName() = this.getAnImportedModuleName() } string getAnImportedModuleName() { exists(Import i | i.getEnclosingModule() = this | result = i.getAnImportedModuleName()) @@ -142,22 +124,23 @@ class Module extends Module_, Scope, AstNode { } /** Whether name is declared in the __all__ list of this module */ - predicate declaredInAll(string name) - { + predicate declaredInAll(string name) { exists(AssignStmt a, GlobalVariable all | - a.defines(all) and a.getScope() = this and - all.getId() = "__all__" and ((List)a.getValue()).getAnElt().(StrConst).getText() = name + a.defines(all) and + a.getScope() = this and + all.getId() = "__all__" and + a.getValue().(List).getAnElt().(StrConst).getText() = name ) } - override AstNode getAChildNode() { - result = this.getAStmt() - } + override AstNode getAChildNode() { result = this.getAStmt() } predicate hasFromFuture(string attr) { exists(Import i, ImportMember im, ImportExpr ie, Alias a, Name name | - im.getModule() = ie and ie.getName() = "__future__" and - a.getAsname() = name and name.getId() = attr and + im.getModule() = ie and + ie.getName() = "__future__" and + a.getAsname() = name and + name.getId() = attr and i.getASubExpression() = im and i.getAName() = a and i.getEnclosingModule() = this @@ -165,55 +148,40 @@ class Module extends Module_, Scope, AstNode { } /** Gets the path element from which this module was loaded. */ - Container getLoadPath() { - result = this.getPath().getImportRoot() - } + Container getLoadPath() { result = this.getPath().getImportRoot() } /** Holds if this module is in the standard library for version `major.minor` */ - predicate inStdLib(int major, int minor) { - this.getLoadPath().isStdLibRoot(major, minor) - } + predicate inStdLib(int major, int minor) { this.getLoadPath().isStdLibRoot(major, minor) } /** Holds if this module is in the standard library */ - predicate inStdLib() { - this.getLoadPath().isStdLibRoot() - } + predicate inStdLib() { this.getLoadPath().isStdLibRoot() } - override - predicate containsInScope(AstNode inner) { - Scope.super.containsInScope(inner) - } + override predicate containsInScope(AstNode inner) { Scope.super.containsInScope(inner) } - override - predicate contains(AstNode inner) { - Scope.super.contains(inner) - } + override predicate contains(AstNode inner) { Scope.super.contains(inner) } /** Gets the kind of this module. */ override string getKind() { - if this.isPackage() then - result = "Package" + if this.isPackage() + then result = "Package" else ( not exists(Module_.super.getKind()) and result = "Module" or result = Module_.super.getKind() ) } - } - bindingset[name] private predicate legalDottedName(string name) { name.regexpMatch("(\\p{L}|_)(\\p{L}|\\d|_)*(\\.(\\p{L}|_)(\\p{L}|\\d|_)*)*") } bindingset[name] -private predicate legalShortName(string name) { - name.regexpMatch("(\\p{L}|_)(\\p{L}|\\d|_)*") -} +private predicate legalShortName(string name) { name.regexpMatch("(\\p{L}|_)(\\p{L}|\\d|_)*") } -/** Holds if `f` is potentially a source package. +/** + * Holds if `f` is potentially a source package. * Does it have an __init__.py file (or --respect-init=False for Python 2) and is it within the source archive? */ private predicate isPotentialSourcePackage(Folder f) { @@ -240,8 +208,12 @@ string moduleNameFromFile(Container file) { result = moduleNameFromFile(file.getParent()) + "." + basename ) or - isPotentialSourcePackage(file) and result = file.getStem() and - (not isPotentialSourcePackage(file.getParent()) or not legalShortName(file.getParent().getBaseName())) + isPotentialSourcePackage(file) and + result = file.getStem() and + ( + not isPotentialSourcePackage(file.getParent()) or + not legalShortName(file.getParent().getBaseName()) + ) or result = file.getStem() and file.getParent() = file.getImportRoot() or @@ -253,8 +225,8 @@ private predicate isStubRoot(Folder f) { f.getAbsolutePath().matches("%/data/python/stubs") } - -/** Holds if the Container `c` should be the preferred file or folder for +/** + * Holds if the Container `c` should be the preferred file or folder for * the given name when performing imports. * Trivially true for any container if it is the only one with its name. * However, if there are several modules with the same name, then diff --git a/python/ql/src/semmle/python/Operations.qll b/python/ql/src/semmle/python/Operations.qll index 5931a88fce5..c6dd102350c 100644 --- a/python/ql/src/semmle/python/Operations.qll +++ b/python/ql/src/semmle/python/Operations.qll @@ -2,123 +2,86 @@ import python /** Base class for operators */ class Operator extends Operator_ { - /** Gets the name of the special method used to implement this operator */ string getSpecialMethodName() { none() } - } /* Unary Expression and its operators */ - /** A unary expression: (`+x`), (`-x`) or (`~x`) */ class UnaryExpr extends UnaryExpr_ { - - override Expr getASubExpression() { - result = this.getOperand() - } - + override Expr getASubExpression() { result = this.getOperand() } } /** A unary operator: `+`, `-`, `~` or `not` */ class Unaryop extends Unaryop_ { - /** Gets the name of the special method used to implement this operator */ string getSpecialMethodName() { none() } - } /** An invert (`~`) unary operator */ class Invert extends Invert_ { - override string getSpecialMethodName() { result = "__invert__" } - } -/** A positive (`+`) unary operator */ +/** A positive (`+`) unary operator */ class UAdd extends UAdd_ { - override string getSpecialMethodName() { result = "__pos__" } - } /** A negation (`-`) unary operator */ class USub extends USub_ { - override string getSpecialMethodName() { result = "__neg__" } - } /** A `not` unary operator */ class Not extends Not_ { - override string getSpecialMethodName() { none() } - } - /* Binary Operation and its operators */ - /** A binary expression, such as `x + y` */ class BinaryExpr extends BinaryExpr_ { - - override Expr getASubExpression() { - result = this.getLeft() or result = this.getRight() - } - + override Expr getASubExpression() { result = this.getLeft() or result = this.getRight() } } /** A power (`**`) binary operator */ class Pow extends Pow_ { - override string getSpecialMethodName() { result = "__pow__" } - } /** A right shift (`>>`) binary operator */ class RShift extends RShift_ { - override string getSpecialMethodName() { result = "__rshift__" } - } /** A subtract (`-`) binary operator */ class Sub extends Sub_ { - override string getSpecialMethodName() { result = "__sub__" } - } /** A bitwise and (`&`) binary operator */ class BitAnd extends BitAnd_ { - override string getSpecialMethodName() { result = "__and__" } - } /** A bitwise or (`|`) binary operator */ class BitOr extends BitOr_ { - override string getSpecialMethodName() { result = "__or__" } - } /** A bitwise exclusive-or (`^`) binary operator */ class BitXor extends BitXor_ { - override string getSpecialMethodName() { result = "__xor__" } - } /** An add (`+`) binary operator */ class Add extends Add_ { - override string getSpecialMethodName() { result = "__add__" } } /** An (true) divide (`/`) binary operator */ class Div extends Div_ { - - override string getSpecialMethodName() { + override string getSpecialMethodName() { result = "__truediv__" or major_version() = 2 and result = "__div__" @@ -127,185 +90,123 @@ class Div extends Div_ { /** An floor divide (`//`) binary operator */ class FloorDiv extends FloorDiv_ { - override string getSpecialMethodName() { result = "__floordiv__" } - } /** A left shift (`<<`) binary operator */ class LShift extends LShift_ { - override string getSpecialMethodName() { result = "__lshift__" } - } /** A modulo (`%`) binary operator, which includes string formatting */ class Mod extends Mod_ { - override string getSpecialMethodName() { result = "__mod__" } - } /** A multiplication (`*`) binary operator */ class Mult extends Mult_ { - override string getSpecialMethodName() { result = "__mul__" } - } /** A matrix multiplication (`@`) binary operator */ class MatMult extends MatMult_ { - override string getSpecialMethodName() { result = "__matmul__" } - } /* Comparison Operation and its operators */ - /** A comparison operation, such as `x`) comparison operator */ class Gt extends Gt_ { - - override string getSymbol() { - result = ">" - } + override string getSymbol() { result = ">" } override string getSpecialMethodName() { result = "__gt__" } - } /** A greater than or equals (`>=`) comparison operator */ class GtE extends GtE_ { - - override string getSymbol() { - result = ">=" - } + override string getSymbol() { result = ">=" } override string getSpecialMethodName() { result = "__ge__" } - } /** An `in` comparison operator */ class In extends In_ { - - override string getSymbol() { - result = "in" - } - + override string getSymbol() { result = "in" } } /** An `is` comparison operator */ class Is extends Is_ { - - override string getSymbol() { - result = "is" - } - + override string getSymbol() { result = "is" } } /** An `is not` comparison operator */ class IsNot extends IsNot_ { - - override string getSymbol() { - result = "is not" - } - + override string getSymbol() { result = "is not" } } /** An equals (`==`) comparison operator */ class Eq extends Eq_ { - - override string getSymbol() { - result = "==" - } + override string getSymbol() { result = "==" } override string getSpecialMethodName() { result = "__eq__" } - } /** A less than (`<`) comparison operator */ class Lt extends Lt_ { - - override string getSymbol() { - result = "<" - } + override string getSymbol() { result = "<" } override string getSpecialMethodName() { result = "__lt__" } - } /** A less than or equals (`<=`) comparison operator */ class LtE extends LtE_ { - - override string getSymbol() { - result = "<=" - } + override string getSymbol() { result = "<=" } override string getSpecialMethodName() { result = "__le__" } - } /** A not equals (`!=`) comparison operator */ class NotEq extends NotEq_ { - - override string getSymbol() { - result = "!=" - } + override string getSymbol() { result = "!=" } override string getSpecialMethodName() { result = "__ne__" } - } /** An `not in` comparison operator */ class NotIn extends NotIn_ { - - override string getSymbol() { - result = "not in" - } - + override string getSymbol() { result = "not in" } } /* Boolean Operation (and/or) and its operators */ - /** A boolean shortcut (and/or) operation */ class BoolExpr extends BoolExpr_ { - - override Expr getASubExpression() { - result = this.getAValue() - } + override Expr getASubExpression() { result = this.getAValue() } string getOperator() { this.getOp() instanceof And and result = "and" @@ -315,30 +216,24 @@ class BoolExpr extends BoolExpr_ { /** Whether part evaluates to partIsTrue if this evaluates to wholeIsTrue */ predicate impliesValue(Expr part, boolean partIsTrue, boolean wholeIsTrue) { - if this.getOp() instanceof And then ( + if this.getOp() instanceof And + then ( wholeIsTrue = true and partIsTrue = true and part = this.getAValue() or - wholeIsTrue = true and ((BoolExpr)this.getAValue()).impliesValue(part, partIsTrue, true) + wholeIsTrue = true and this.getAValue().(BoolExpr).impliesValue(part, partIsTrue, true) ) else ( wholeIsTrue = false and partIsTrue = false and part = this.getAValue() or - wholeIsTrue = false and ((BoolExpr)this.getAValue()).impliesValue(part, partIsTrue, false) + wholeIsTrue = false and this.getAValue().(BoolExpr).impliesValue(part, partIsTrue, false) ) } - } /** A short circuit boolean operator, and/or */ -class Boolop extends Boolop_ { - -} +class Boolop extends Boolop_ { } /** An `and` boolean operator */ -class And extends And_ { - -} +class And extends And_ { } /** An `or` boolean operator */ -class Or extends Or_ { - -} +class Or extends Or_ { } diff --git a/python/ql/src/semmle/python/SSA.qll b/python/ql/src/semmle/python/SSA.qll index 3035166824a..68a6b1db803 100644 --- a/python/ql/src/semmle/python/SSA.qll +++ b/python/ql/src/semmle/python/SSA.qll @@ -2,40 +2,33 @@ import python -/** A single static assignment variable. +/** + * A single static assignment variable. * An SSA variable is a variable which is only assigned once (statically). * SSA variables can be defined as normal variables or by a phi node which can occur at joins in the flow graph. * Definitions without uses do not have a SSA variable. */ -class SsaVariable extends @py_ssa_var{ - - SsaVariable() { - py_ssa_var(this, _) - } +class SsaVariable extends @py_ssa_var { + SsaVariable() { py_ssa_var(this, _) } /** Gets the source variable */ - Variable getVariable() { - py_ssa_var(this, result) - } + Variable getVariable() { py_ssa_var(this, result) } /** Gets a use of this variable */ - ControlFlowNode getAUse() { - py_ssa_use(result, this) - } + ControlFlowNode getAUse() { py_ssa_use(result, this) } /** Gets the definition (which may be a deletion) of this SSA variable */ - ControlFlowNode getDefinition() { - py_ssa_defn(this, result) - } + ControlFlowNode getDefinition() { py_ssa_defn(this, result) } - /** Gets an argument of the phi function defining this variable. + /** + * Gets an argument of the phi function defining this variable. * This predicate uses the raw SSA form produced by the extractor. - * In general, you should use `getAPrunedPhiInput()` instead. */ - SsaVariable getAPhiInput() { - py_ssa_phi(this, result) - } + * In general, you should use `getAPrunedPhiInput()` instead. + */ + SsaVariable getAPhiInput() { py_ssa_phi(this, result) } - /** Gets the edge(s) (result->this.getDefinition()) on which the SSA variable 'input' defines this SSA variable. + /** + * Gets the edge(s) (result->this.getDefinition()) on which the SSA variable 'input' defines this SSA variable. * For each incoming edge `X->B`, where `B` is the basic block containing this phi-node, only one of the input SSA variables * for this phi-node is live. This predicate returns the predecessor block such that the variable 'input' * is the live variable on the edge result->B. @@ -44,23 +37,25 @@ class SsaVariable extends @py_ssa_var{ input = this.getAPhiInput() and result = this.getAPredecessorBlockForPhi() and input.getDefinition().getBasicBlock().dominates(result) and - /* Beware the case where an SSA variable that is an input on one edge dominates another edge. + /* + * Beware the case where an SSA variable that is an input on one edge dominates another edge. * Consider (in SSA form): * x0 = 0 * if cond: * x1 = 1 * x2 = phi(x0, x1) * use(x2) - * + * * The definition of x0 dominates the exit from the block x1=1, even though it does not reach it. * Hence we need to check that no other definition dominates the edge and actually reaches it. * Note that if a dominates c and b dominates c, then either a dominates b or vice-versa. */ + not exists(SsaVariable other, BasicBlock other_def | not other = input and other = this.getAPhiInput() and other_def = other.getDefinition().getBasicBlock() - | + | other_def.dominates(result) and input.getDefinition().getBasicBlock().strictlyDominates(other_def) ) @@ -81,22 +76,16 @@ class SsaVariable extends @py_ssa_var{ result = this.getAPhiInput().getAnUltimateDefinition() } - string toString() { - result = "SSA Variable " + this.getId() - } + string toString() { result = "SSA Variable " + this.getId() } - Location getLocation() { - result = this.getDefinition().getLocation() - } + Location getLocation() { result = this.getDefinition().getLocation() } /** Gets the id (name) of this variable */ - string getId() { - result = this.getVariable().getId() - } + string getId() { result = this.getVariable().getId() } /** Gets the incoming edges for a Phi node. */ private BasicBlock getAPredecessorBlockForPhi() { - exists(getAPhiInput()) and + exists(getAPhiInput()) and result.getASuccessor() = this.getDefinition().getBasicBlock() } @@ -112,11 +101,13 @@ class SsaVariable extends @py_ssa_var{ or exists(SsaVariable var | var = this.getAPhiInput() | var.reachableWithoutDefinition()) or - /* For phi-nodes, there must be a corresponding phi-input for each control-flow + /* + * For phi-nodes, there must be a corresponding phi-input for each control-flow * predecessor. Otherwise, the variable will be undefined on that incoming edge. * WARNING: the same phi-input may cover multiple predecessors, so this check * cannot be done by counting. */ + exists(BasicBlock incoming | incoming = this.getAPredecessorBlockForPhi() and not this.getAPhiInput().getDefinition().getBasicBlock().dominates(incoming) @@ -131,11 +122,13 @@ class SsaVariable extends @py_ssa_var{ or exists(SsaVariable var | var = this.getAPrunedPhiInput() | var.maybeUndefined()) or - /* For phi-nodes, there must be a corresponding phi-input for each control-flow + /* + * For phi-nodes, there must be a corresponding phi-input for each control-flow * predecessor. Otherwise, the variable will be undefined on that incoming edge. * WARNING: the same phi-input may cover multiple predecessors, so this check * cannot be done by counting. */ + exists(BasicBlock incoming | reaches_end(incoming) and incoming = this.getAPrunedPredecessorBlockForPhi() and @@ -144,14 +137,17 @@ class SsaVariable extends @py_ssa_var{ } private predicate implicitlyDefined() { - not exists(this.getDefinition()) and not py_ssa_phi(this, _) and + not exists(this.getDefinition()) and + not py_ssa_phi(this, _) and exists(GlobalVariable var | this.getVariable() = var | - globallyDefinedName(var.getId()) or - var.getId() = "__path__" and ((Module)var.getScope()).isPackageInit() + globallyDefinedName(var.getId()) + or + var.getId() = "__path__" and var.getScope().(Module).isPackageInit() ) } - /** Gets the global variable that is accessed if this local is undefined. + /** + * Gets the global variable that is accessed if this local is undefined. * Only applies to local variables in class scopes. */ GlobalVariable getFallbackGlobal() { @@ -163,28 +159,26 @@ class SsaVariable extends @py_ssa_var{ ) } - /* Whether this SSA variable is the first parameter of a method + /* + * Whether this SSA variable is the first parameter of a method * (regardless of whether it is actually called self or not) */ + predicate isSelf() { - exists(Function func | - func.isMethod() - and + exists(Function func | + func.isMethod() and this.getDefinition().getNode() = func.getArg(0) ) } } private predicate reaches_end(BasicBlock b) { - not exits_early(b) - and + not exits_early(b) and ( - /* Entry point */ - not exists(BasicBlock prev | prev.getASuccessor() = b) - or - exists(BasicBlock prev | prev.getASuccessor() = b | - reaches_end(prev) - ) + /* Entry point */ + not exists(BasicBlock prev | prev.getASuccessor() = b) + or + exists(BasicBlock prev | prev.getASuccessor() = b | reaches_end(prev)) ) } @@ -209,32 +203,19 @@ private predicate builtin_constant(string name) { } private predicate auto_name(string name) { - name = "__file__" or name = "__builtins__" or name = "__name__" + name = "__file__" or name = "__builtins__" or name = "__name__" } /** Whether this name is (almost) always defined, ie. it is a builtin or VM defined name */ -predicate globallyDefinedName(string name) { - builtin_constant(name) or auto_name(name) -} +predicate globallyDefinedName(string name) { builtin_constant(name) or auto_name(name) } /** An SSA variable that is backed by a global variable */ class GlobalSsaVariable extends EssaVariable { + GlobalSsaVariable() { this.getSourceVariable() instanceof GlobalVariable } - GlobalSsaVariable() { - this.getSourceVariable() instanceof GlobalVariable - } - - GlobalVariable getVariable() { - result = this.getSourceVariable() - } - - string getId() { - result = this.getVariable().getId() - } - - override string toString() { - result = "GSSA Variable " + this.getId() - } + GlobalVariable getVariable() { result = this.getSourceVariable() } + string getId() { result = this.getVariable().getId() } + override string toString() { result = "GSSA Variable " + this.getId() } } diff --git a/python/ql/src/semmle/python/Scope.qll b/python/ql/src/semmle/python/Scope.qll index 112b3d10cc5..1fab7f77013 100755 --- a/python/ql/src/semmle/python/Scope.qll +++ b/python/ql/src/semmle/python/Scope.qll @@ -1,80 +1,58 @@ import python -/** A Scope. A scope is the lexical extent over which all identifiers with the same name refer to the same variable. +/** + * A Scope. A scope is the lexical extent over which all identifiers with the same name refer to the same variable. * Modules, Classes and Functions are all Scopes. There are no other scopes. - * The scopes for expressions that create new scopes, lambdas and comprehensions, are handled by creating an anonymous Function. */ + * The scopes for expressions that create new scopes, lambdas and comprehensions, are handled by creating an anonymous Function. + */ class Scope extends Scope_ { + Module getEnclosingModule() { result = this.getEnclosingScope().getEnclosingModule() } - Module getEnclosingModule() { - result = this.getEnclosingScope().getEnclosingModule() - } - - /** This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. + /** + * This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. * The reason for this is to avoid confusion around use of `x.getScope+()` where `x` might be an * `AstNode` or a `Variable`. Forcing the users to write `x.getScope().getEnclosingScope*()` ensures that * the apparent semantics and the actual semantics coincide. * [ Gets the scope enclosing this scope (modules have no enclosing scope) ] */ - Scope getScope() { - none() - } + Scope getScope() { none() } /** Gets the scope enclosing this scope (modules have no enclosing scope) */ - Scope getEnclosingScope() { - none() - } + Scope getEnclosingScope() { none() } /** Gets the statements forming the body of this scope */ - StmtList getBody() { - none() - } + StmtList getBody() { none() } /** Gets the nth statement of this scope */ - Stmt getStmt(int n) { - none() - } + Stmt getStmt(int n) { none() } /** Gets a top-level statement in this scope */ - Stmt getAStmt() { - none() - } + Stmt getAStmt() { none() } - Location getLocation() { - none() - } + Location getLocation() { none() } /** Gets the name of this scope */ - string getName() { - py_strs(result, this, 0) - } + string getName() { py_strs(result, this, 0) } /** Gets the docstring for this scope */ - StrConst getDocString() { - result = ((ExprStmt)this.getStmt(0)).getValue() - } + StrConst getDocString() { result = this.getStmt(0).(ExprStmt).getValue() } /** Gets the entry point into this Scope's control flow graph */ - ControlFlowNode getEntryNode() { - py_scope_flow(result, this, -1) - } + ControlFlowNode getEntryNode() { py_scope_flow(result, this, -1) } /** Gets the non-explicit exit from this Scope's control flow graph */ - ControlFlowNode getFallthroughNode() { - py_scope_flow(result, this, 0) - } + ControlFlowNode getFallthroughNode() { py_scope_flow(result, this, 0) } /** Gets the exit of this scope following from a return statement */ - ControlFlowNode getReturnNode() { - py_scope_flow(result, this, 2) - } + ControlFlowNode getReturnNode() { py_scope_flow(result, this, 2) } /** Gets an exit from this Scope's control flow graph */ - ControlFlowNode getAnExitNode() { - exists (int i | py_scope_flow(result, this, i) and i >= 0) - } + ControlFlowNode getAnExitNode() { exists(int i | py_scope_flow(result, this, i) and i >= 0) } - /** Gets an exit from this Scope's control flow graph, - * that does not result from an exception */ + /** + * Gets an exit from this Scope's control flow graph, + * that does not result from an exception + */ ControlFlowNode getANormalExit() { result = this.getFallthroughNode() or @@ -82,9 +60,7 @@ class Scope extends Scope_ { } /** Holds if this a top-level (non-nested) class or function */ - predicate isTopLevel() { - this.getEnclosingModule() = this.getEnclosingScope() - } + predicate isTopLevel() { this.getEnclosingModule() = this.getEnclosingScope() } /** Holds if this scope is deemed to be public */ predicate isPublic() { @@ -93,10 +69,9 @@ class Scope extends Scope_ { /* Not implicitly private */ this.getName().charAt(0) != "_" and ( - this instanceof Module + this instanceof Module or - exists(Module m | - m = this.getEnclosingScope() and m.isPublic() | + exists(Module m | m = this.getEnclosingScope() and m.isPublic() | /* If the module has an __all__, is this in it */ not exists(m.getAnExport()) or @@ -116,66 +91,63 @@ class Scope extends Scope_ { exists(Scope inner | inner.getEnclosingScope() = this | inner.contains(a)) } - /** Holds if this scope can be expected to execute before `other`. + /** + * Holds if this scope can be expected to execute before `other`. * Modules precede functions and methods in those modules * `__init__` precedes other methods. `__enter__` precedes `__exit__`. - * NOTE that this is context-insensitive, so a module "precedes" a function + * NOTE that this is context-insensitive, so a module "precedes" a function * in that module, even if that function is called from the module scope. */ predicate precedes(Scope other) { - exists(Function f, string name | - f = other and name = f.getName() | - if f.isMethod() then ( + exists(Function f, string name | f = other and name = f.getName() | + if f.isMethod() + then // The __init__ method is preceded by the enclosing module this = f.getEnclosingModule() and name = "__init__" or exists(Class c, string pred_name | // __init__ -> __enter__ -> __exit__ // __init__ -> other-methods - f.getScope() = c and ( + f.getScope() = c and + ( pred_name = "__init__" and not name = "__init__" and not name = "__exit__" or pred_name = "__enter__" and name = "__exit__" ) - | + | this.getScope() = c and pred_name = this.(Function).getName() or not exists(Function pre_func | pre_func.getName() = pred_name and pre_func.getScope() = c - ) and this = other.getEnclosingModule() + ) and + this = other.getEnclosingModule() ) - ) else ( + else // Normal functions are preceded by the enclosing module this = f.getEnclosingModule() - ) ) } - /** Gets the evaluation scope for code in this (lexical) scope. + /** + * Gets the evaluation scope for code in this (lexical) scope. * This is usually the scope itself, but may be an enclosing scope. * Notably, for list comprehensions in Python 2. */ - Scope getEvaluatingScope() { - result = this - } + Scope getEvaluatingScope() { result = this } - /** Holds if this scope is in the source archive, + /** + * Holds if this scope is in the source archive, * that is it is part of the code specified, not library code */ - predicate inSource() { - exists(this.getEnclosingModule().getFile().getRelativePath()) - } + predicate inSource() { exists(this.getEnclosingModule().getFile().getRelativePath()) } - Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() - } + Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } /** Whether this contains `inner` syntactically and `inner` has the same scope as `this` */ predicate containsInScope(AstNode inner) { this.getBody().contains(inner) and this = inner.getScope() } - } diff --git a/python/ql/src/semmle/python/SelfAttribute.qll b/python/ql/src/semmle/python/SelfAttribute.qll index e970aa6c3d9..c40b3b3c0be 100644 --- a/python/ql/src/semmle/python/SelfAttribute.qll +++ b/python/ql/src/semmle/python/SelfAttribute.qll @@ -1,23 +1,19 @@ -/** Utilities to support queries about instance attribute accesses of +/** + * Utilities to support queries about instance attribute accesses of * the form `self.attr`. */ import python private import semmle.python.pointsto.Filters -/** An attribute access where the left hand side of the attribute expression - * is `self`. - */ +/** + * An attribute access where the left hand side of the attribute expression + * is `self`. + */ class SelfAttribute extends Attribute { + SelfAttribute() { self_attribute(this, _) } - SelfAttribute() { - self_attribute(this, _) - } - - Class getClass() { - self_attribute(this, result) - } - + Class getClass() { self_attribute(this, result) } } /** Whether variable 'self' is the self variable in method 'method' */ @@ -29,8 +25,7 @@ private predicate self_variable(Function method, Variable self) { /** Whether attribute is an access of the form `self.attr` in the body of the class 'cls' */ private predicate self_attribute(Attribute attr, Class cls) { - exists(Function f, Variable self | - self_variable(f, self) | + exists(Function f, Variable self | self_variable(f, self) | self.getAnAccess() = attr.getObject() and cls = f.getScope+() ) @@ -38,14 +33,12 @@ private predicate self_attribute(Attribute attr, Class cls) { /** Helper class for UndefinedClassAttribute.ql & MaybeUndefinedClassAttribute.ql */ class SelfAttributeRead extends SelfAttribute { - SelfAttributeRead() { this.getCtx() instanceof Load and - // Be stricter for loads. + // Be stricter for loads. // We want to generous as to what is defined (i.e. stores), // but strict as to what needs to be defined (i.e. loads). - exists(ClassObject cls, FunctionObject func | - cls.declaredAttribute(_) = func | + exists(ClassObject cls, FunctionObject func | cls.declaredAttribute(_) = func | func.getFunction() = this.getScope() and cls.getPyClass() = this.getClass() ) @@ -59,35 +52,28 @@ class SelfAttributeRead extends SelfAttribute { ) } - pragma [noinline] predicate locallyDefined() { + pragma[noinline] + predicate locallyDefined() { exists(SelfAttributeStore store | - this.getName() = store.getName() and - this.getScope() = store.getScope() | + this.getName() = store.getName() and + this.getScope() = store.getScope() + | store.getAFlowNode().strictlyDominates(this.getAFlowNode()) ) } - } class SelfAttributeStore extends SelfAttribute { + SelfAttributeStore() { this.getCtx() instanceof Store } - SelfAttributeStore() { - this.getCtx() instanceof Store - } - - Expr getAssignedValue() { - exists(Assign a | a.getATarget() = this | - result = a.getValue() - ) - } - + Expr getAssignedValue() { exists(Assign a | a.getATarget() = this | result = a.getValue()) } } private predicate attr_assigned_in_method_arg_n(FunctionObject method, string name, int n) { exists(SsaVariable param | method.getFunction().getArg(n).asName() = param.getDefinition().getNode() - | - exists(AttrNode attr | + | + exists(AttrNode attr | attr.getObject(name) = param.getAUse() and attr.isStore() ) diff --git a/python/ql/src/semmle/python/Stmts.qll b/python/ql/src/semmle/python/Stmts.qll index 4d8c45b70a8..cc67747923a 100644 --- a/python/ql/src/semmle/python/Stmts.qll +++ b/python/ql/src/semmle/python/Stmts.qll @@ -2,34 +2,21 @@ import python /** A statement */ class Stmt extends Stmt_, AstNode { - /** Gets the scope immediately enclosing this statement */ - override Scope getScope() { - py_scopes(this, result) - } + override Scope getScope() { py_scopes(this, result) } - override string toString() { - result = "Stmt" - } + override string toString() { result = "Stmt" } /** Gets the module enclosing this statement */ - Module getEnclosingModule() { - result = this.getScope().getEnclosingModule() - } + Module getEnclosingModule() { result = this.getScope().getEnclosingModule() } - override Location getLocation() { - result = Stmt_.super.getLocation() - } + override Location getLocation() { result = Stmt_.super.getLocation() } /** Gets an immediate (non-nested) sub-expression of this statement */ - Expr getASubExpression() { - none() - } + Expr getASubExpression() { none() } /** Gets an immediate (non-nested) sub-statement of this statement */ - Stmt getASubStatement() { - none() - } + Stmt getASubStatement() { none() } override AstNode getAChildNode() { result = this.getASubExpression() @@ -42,8 +29,8 @@ class Stmt extends Stmt_, AstNode { this.containsInScope(result.getNode()) } - - /** Gets a control flow node for an entry into this statement. + /** + * Gets a control flow node for an entry into this statement. */ ControlFlowNode getAnEntryNode() { result = this.possibleEntryNode() and @@ -60,131 +47,94 @@ class Stmt extends Stmt_, AstNode { exists(If ifstmt | ifstmt.getTest().(ImmutableLiteral).booleanValue() = false and ifstmt.getBody().contains(this) or - ifstmt.getTest().(ImmutableLiteral).booleanValue() = true and ifstmt.getOrelse().contains(this) + ifstmt.getTest().(ImmutableLiteral).booleanValue() = true and + ifstmt.getOrelse().contains(this) ) or exists(While whilestmt | - whilestmt.getTest().(ImmutableLiteral).booleanValue() = false and whilestmt.getBody().contains(this) + whilestmt.getTest().(ImmutableLiteral).booleanValue() = false and + whilestmt.getBody().contains(this) ) } - /** Gets the final statement in this statement, ordered by location. + /** + * Gets the final statement in this statement, ordered by location. * Will be this statement if not a compound statement. */ - Stmt getLastStatement() { - result = this - } - + Stmt getLastStatement() { result = this } } /** A statement that includes a binding (except imports) */ class Assign extends Assign_ { - /** Use ControlFlowNodes and SsaVariables for data-flow analysis. */ - predicate defines(Variable v) { - this.getATarget().defines(v) - } + predicate defines(Variable v) { this.getATarget().defines(v) } override Expr getASubExpression() { result = this.getATarget() or result = this.getValue() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } } /** An assignment statement */ class AssignStmt extends Assign { - /* syntax: Expr, ... = Expr */ + AssignStmt() { not this instanceof FunctionDef and not this instanceof ClassDef } - AssignStmt() { - not this instanceof FunctionDef and not this instanceof ClassDef - } - - override string toString() { - result = "AssignStmt" - } + override string toString() { result = "AssignStmt" } } /** An augmented assignment statement, such as `x += y` */ class AugAssign extends AugAssign_ { - /* syntax: Expr += Expr */ + override Expr getASubExpression() { result = this.getOperation() } - override Expr getASubExpression() { - result = this.getOperation() - } + Expr getTarget() { result = this.getOperation().(BinaryExpr).getLeft() } - Expr getTarget() { - result = ((BinaryExpr)this.getOperation()).getLeft() - } + Expr getValue() { result = this.getOperation().(BinaryExpr).getRight() } - Expr getValue() { - result = ((BinaryExpr)this.getOperation()).getRight() - } - - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } } /** An annotated assignment statement, such as `x: int = 0` */ class AnnAssign extends AnnAssign_ { - /* syntax: Expr: Expr = Expr */ - override Expr getASubExpression() { result = this.getAnnotation() or result = this.getTarget() or result = this.getValue() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } /** Holds if the value of the annotation of this assignment is stored at runtime. */ predicate isStored() { - not this.getScope() instanceof Function - and + not this.getScope() instanceof Function and exists(Name n | - n = this.getTarget() - and + n = this.getTarget() and not n.isParenthesized() ) } - } /** An exec statement */ class Exec extends Exec_ { - /* syntax: exec Expr */ - override Expr getASubExpression() { result = this.getBody() or result = this.getGlobals() or result = this.getLocals() } - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** An except statement (part of a `try` statement), such as `except IOError as err:` */ class ExceptStmt extends ExceptStmt_ { - /* syntax: except Expr [ as Expr ]: */ - /** Gets the immediately enclosing try statement */ - Try getTry() { - result.getAHandler() = this - } + Try getTry() { result.getAHandler() = this } override Expr getASubExpression() { result = this.getName() @@ -192,96 +142,54 @@ class ExceptStmt extends ExceptStmt_ { result = this.getType() } - override Stmt getASubStatement() { - result = this.getAStmt() - } - - override Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() - } + override Stmt getASubStatement() { result = this.getAStmt() } + override Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } } /** An assert statement, such as `assert a == b, "A is not equal to b"` */ class Assert extends Assert_ { - /* syntax: assert Expr [, Expr] */ + override Expr getASubExpression() { result = this.getMsg() or result = this.getTest() } - override Expr getASubExpression() { - result = this.getMsg() or result = this.getTest() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A break statement */ class Break extends Break_ { - /* syntax: assert Expr [, Expr] */ + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A continue statement */ class Continue extends Continue_ { - /* syntax: continue */ + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A delete statement, such as `del x[-1]` */ class Delete extends Delete_ { - /* syntax: del Expr, ... */ + override Expr getASubExpression() { result = this.getATarget() } - override Expr getASubExpression() { - result = this.getATarget() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** An expression statement, such as `len(x)` or `yield y` */ class ExprStmt extends ExprStmt_ { - /* syntax: Expr */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A for statement, such as `for x in y: print(x)` */ class For extends For_ { - /* syntax: for varname in Expr: ... */ - override Stmt getASubStatement() { result = this.getAStmt() or result = this.getAnOrelse() @@ -292,39 +200,26 @@ class For extends For_ { result = this.getIter() } - override Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() - } - + override Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } } /** A global statement, such as `global var` */ class Global extends Global_ { - /* syntax: global varname */ + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } } /** An if statement, such as `if eggs: print("spam")` */ class If extends If_ { - /* syntax: if Expr: ... */ - override Stmt getASubStatement() { result = this.getAStmt() or result = this.getAnOrelse() } - override Expr getASubExpression() { - result = this.getTest() - } + override Expr getASubExpression() { result = this.getTest() } /** Whether this if statement takes the form `if __name__ == "__main__":` */ predicate isNameEqMain() { @@ -343,11 +238,13 @@ class If extends If_ { /** Whether this if statement starts with the keyword `elif` */ predicate isElif() { - /* The Python parser turns all elif chains into nested if-else statements. + /* + * The Python parser turns all elif chains into nested if-else statements. * An `elif` can be identified as it is the first statement in an `else` block * and it is not indented relative to its parent `if`. */ - exists(If i | + + exists(If i | i.getOrelse(0) = this and this.getLocation().getStartColumn() = i.getLocation().getStartColumn() ) @@ -365,74 +262,49 @@ class If extends If_ { not exists(this.getOrelse()) and result = this.getBody().getLastItem().getLastStatement() } - } /** A nonlocal statement, such as `nonlocal var` */ class Nonlocal extends Nonlocal_ { - /* syntax: nonlocal varname */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } - - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } Variable getAVariable() { result.getScope() = this.getScope() and result.getId() = this.getAName() } - } /** A pass statement */ class Pass extends Pass_ { - /* syntax: pass */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } - - override Expr getASubExpression() { - none() - } - + override Expr getASubExpression() { none() } } /** A print statement (Python 2 only), such as `print 0` */ class Print extends Print_ { - /* syntax: print Expr, ... */ - - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } override Expr getASubExpression() { result = this.getAValue() or result = this.getDest() } - } /** A raise statement, such as `raise CompletelyDifferentException()` */ class Raise extends Raise_ { - /* syntax: raise Expr */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } + override Expr getASubExpression() { py_exprs(result, _, this, _) } - override Expr getASubExpression() { - py_exprs(result, _, this, _) - } - - /** The expression immediately following the `raise`, this is the + /** + * The expression immediately following the `raise`, this is the * exception raised, but not accounting for tuples in Python 2. */ Expr getException() { @@ -442,12 +314,10 @@ class Raise extends Raise_ { } /** The exception raised, accounting for tuples in Python 2. */ - Expr getRaised() - { - exists(Expr raw | - raw = this.getException() | - if (not major_version() = 2 or not exists(raw.(Tuple).getAnElt())) then - result = raw + Expr getRaised() { + exists(Expr raw | raw = this.getException() | + if not major_version() = 2 or not exists(raw.(Tuple).getAnElt()) + then result = raw else /* In Python 2 raising a tuple will result in the first element of the tuple being raised. */ result = raw.(Tuple).getElt(0) @@ -457,27 +327,16 @@ class Raise extends Raise_ { /** A return statement, such as return None */ class Return extends Return_ { - /* syntax: return Expr */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } - - override Expr getASubExpression() { - result = this.getValue() - } - + override Expr getASubExpression() { result = this.getValue() } } /** A try statement */ class Try extends Try_ { - /* syntax: try: ... */ - - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } override Stmt getASubStatement() { result = this.getAHandler() or @@ -486,14 +345,10 @@ class Try extends Try_ { result = this.getAnOrelse() } - override ExceptStmt getHandler(int i) { - result = Try_.super.getHandler(i) - } + override ExceptStmt getHandler(int i) { result = Try_.super.getHandler(i) } /** Gets an exception handler of this try statement. */ - override ExceptStmt getAHandler() { - result = Try_.super.getAHandler() - } + override ExceptStmt getAHandler() { result = Try_.super.getAHandler() } override Stmt getLastStatement() { result = this.getFinalbody().getLastItem().getLastStatement() @@ -501,23 +356,21 @@ class Try extends Try_ { not exists(this.getFinalbody()) and result = this.getOrelse().getLastItem().getLastStatement() or - not exists(this.getFinalbody()) and not exists(this.getOrelse()) and + not exists(this.getFinalbody()) and + not exists(this.getOrelse()) and result = this.getHandlers().getLastItem().getLastStatement() or - not exists(this.getFinalbody()) and not exists(this.getOrelse()) and not exists(this.getHandlers()) and + not exists(this.getFinalbody()) and + not exists(this.getOrelse()) and + not exists(this.getHandlers()) and result = this.getBody().getLastItem().getLastStatement() } - } /** A while statement, such as `while parrot_resting():` */ class While extends While_ { - /* syntax: while Expr: ... */ - - override Expr getASubExpression() { - result = this.getTest() - } + override Expr getASubExpression() { result = this.getTest() } override Stmt getASubStatement() { result = this.getAStmt() or @@ -530,75 +383,44 @@ class While extends While_ { not exists(this.getOrelse()) and result = this.getBody().getLastItem().getLastStatement() } - } /** A with statement such as `with f as open("file"): text = f.read()` */ class With extends With_ { - /* syntax: with Expr as varname: ... */ - override Expr getASubExpression() { result = this.getContextExpr() or result = this.getOptionalVars() - } - - override Stmt getASubStatement() { - result = this.getAStmt() - } - - override Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() } + override Stmt getASubStatement() { result = this.getAStmt() } + + override Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } } /** A plain text used in a template is wrapped in a TemplateWrite statement */ class TemplateWrite extends TemplateWrite_ { + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } class AsyncFor extends For { - /* syntax: async for varname in Expr: ... */ - - AsyncFor() { - this.isAsync() - } - + AsyncFor() { this.isAsync() } } class AsyncWith extends With { - /* syntax: async with Expr as varname: ... */ - - AsyncWith() { - this.isAsync() - } - + AsyncWith() { this.isAsync() } } /** A list of statements */ class StmtList extends StmtList_ { - /** Whether this list of statements contains s */ predicate contains(AstNode a) { - exists(Stmt item | - item = this.getAnItem() | - item = a or item.contains(a) - ) + exists(Stmt item | item = this.getAnItem() | item = a or item.contains(a)) } Stmt getLastItem() { result = this.getItem(max(int i | exists(this.getItem(i)))) } - } - - diff --git a/python/ql/src/semmle/python/TestUtils.qll b/python/ql/src/semmle/python/TestUtils.qll index c94dcde0d78..a51d68dcf73 100644 --- a/python/ql/src/semmle/python/TestUtils.qll +++ b/python/ql/src/semmle/python/TestUtils.qll @@ -1,32 +1,29 @@ /* This file contains test-related utility functions */ - import python - /** Removes everything up to the occurrence of `sub` in the string `str` */ - -bindingset[str,sub] +bindingset[str, sub] string remove_prefix_before_substring(string str, string sub) { - exists(int index | - index = str.indexOf(sub) and - result = str.suffix(index) - ) - or - not exists(str.indexOf(sub)) and - result = str + exists(int index | + index = str.indexOf(sub) and + result = str.suffix(index) + ) + or + not exists(str.indexOf(sub)) and + result = str } -/** Removes the part of the `resources/lib` Python library path that may vary - * from machine to machine. */ - +/** + * Removes the part of the `resources/lib` Python library path that may vary + * from machine to machine. + */ string remove_library_prefix(Location loc) { - result = remove_prefix_before_substring(loc.toString(), "resources/lib") + result = remove_prefix_before_substring(loc.toString(), "resources/lib") } /** Returns the location of an AST node in compact form: `basename:line:column` */ string compact_location(AstNode a) { - exists(Location l | - l = a.getLocation() | + exists(Location l | l = a.getLocation() | result = l.getFile().getBaseName() + ":" + l.getStartLine() + ":" + l.getStartColumn() ) -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/Variables.qll b/python/ql/src/semmle/python/Variables.qll index 49f0f1aa4f1..df7ee2d07dd 100644 --- a/python/ql/src/semmle/python/Variables.qll +++ b/python/ql/src/semmle/python/Variables.qll @@ -1,24 +1,19 @@ - import python /** A variable, either a global or local variable (including parameters) */ class Variable extends @py_variable { - Variable() { exists(string name | variable(this, _, name) and - not name = "*" and not name = "$" + not name = "*" and + not name = "$" ) } /** Gets the identifier (name) of this variable */ - string getId() { - variable(this, _, result) - } + string getId() { variable(this, _, result) } - string toString() { - result = "Variable " + this.getId() - } + string toString() { result = "Variable " + this.getId() } /** Gets an access (load or store) of this variable */ Name getAnAccess() { @@ -28,103 +23,70 @@ class Variable extends @py_variable { } /** Gets a load of this variable */ - Name getALoad() { - result.uses(this) - } + Name getALoad() { result.uses(this) } /** Gets a store of this variable */ - Name getAStore() { - result.defines(this) - } + Name getAStore() { result.defines(this) } /** Gets a use of this variable */ - NameNode getAUse() { - result.uses(this) - } + NameNode getAUse() { result.uses(this) } /** Gets the scope of this variable */ - Scope getScope() { - variable(this, result, _) - } + Scope getScope() { variable(this, result, _) } - /** Whether there is an access to this variable outside + /** + * Whether there is an access to this variable outside * of its own scope. Usually occurs in nested functions * or for global variables. */ - predicate escapes() { - exists(Name n | n = this.getAnAccess() | n.getScope() != this.getScope()) - } + predicate escapes() { exists(Name n | n = this.getAnAccess() | n.getScope() != this.getScope()) } /** Whether this variable is a parameter */ - predicate isParameter() { - none() - } - - predicate isSelf() { - none() - } + predicate isParameter() { none() } + predicate isSelf() { none() } } /** A local (function or class) variable */ class LocalVariable extends Variable { - LocalVariable() { exists(Scope s | s = this.getScope() | s instanceof Function or s instanceof Class) } - override string toString() { - result = "Local Variable " + this.getId() - } + override string toString() { result = "Local Variable " + this.getId() } /** Whether this variable is a parameter */ - override predicate isParameter() { - exists(Parameter p | this.getAnAccess() = p) - } + override predicate isParameter() { exists(Parameter p | this.getAnAccess() = p) } /** Holds if this variable is the first parameter of a method. It is not necessarily called "self" */ override predicate isSelf() { - exists(Function f, Parameter self | + exists(Function f, Parameter self | this.getAnAccess() = self and - f.isMethod() and f.getArg(0) = self + f.isMethod() and + f.getArg(0) = self ) } - } -/** A local variable that uses "load fast" semantics, for lookup: - * If the variable is undefined, then raise an exception. +/** + * A local variable that uses "load fast" semantics, for lookup: + * If the variable is undefined, then raise an exception. */ class FastLocalVariable extends LocalVariable { - - FastLocalVariable() { - this.getScope() instanceof FastLocalsFunction - } - + FastLocalVariable() { this.getScope() instanceof FastLocalsFunction } } -/** A local variable that uses "load name" semantics, for lookup: +/** + * A local variable that uses "load name" semantics, for lookup: * If the variable is undefined, then lookup the value in globals(). */ class NameLocalVariable extends LocalVariable { - - NameLocalVariable() { - not this instanceof FastLocalVariable - } - + NameLocalVariable() { not this instanceof FastLocalVariable } } /** A global (module-level) variable */ class GlobalVariable extends Variable { + GlobalVariable() { exists(Module m | m = this.getScope()) } - GlobalVariable() { - exists(Module m | m = this.getScope()) - } - - override string toString() { - result = "Global Variable " + this.getId() - } - + override string toString() { result = "Global Variable " + this.getId() } } - - From 9044ff695942143e7c81207f056ef05c4fe41397 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:42:22 +0100 Subject: [PATCH 115/459] Python: Autoformat rest of `semmle/python`. --- .../semmle/python/dataflow/Implementation.qll | 19 +- .../python/dependencies/Dependencies.qll | 78 ++-- .../python/dependencies/DependencyKind.qll | 20 +- .../python/dependencies/TechInventory.qll | 70 ++- .../ql/src/semmle/python/essa/Definitions.qll | 134 ++---- python/ql/src/semmle/python/essa/Essa.qll | 405 ++++++----------- .../ql/src/semmle/python/essa/SsaCompute.qll | 225 +++++----- .../src/semmle/python/essa/SsaDefinitions.qll | 72 +-- .../semmle/python/filters/GeneratedCode.qll | 127 +++--- python/ql/src/semmle/python/filters/Tests.qll | 19 +- .../ql/src/semmle/python/libraries/Zope.qll | 27 +- python/ql/src/semmle/python/protocols.qll | 24 +- python/ql/src/semmle/python/regex.qll | 416 +++++++++--------- python/ql/src/semmle/python/strings.qll | 42 +- .../src/semmle/python/templates/PyxlTags.qll | 70 +-- .../src/semmle/python/templates/Templates.qll | 17 +- .../semmle/python/values/StringAttributes.qll | 40 +- 17 files changed, 758 insertions(+), 1047 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/Implementation.qll b/python/ql/src/semmle/python/dataflow/Implementation.qll index 9f7d44bdfb6..9e1922a52d9 100644 --- a/python/ql/src/semmle/python/dataflow/Implementation.qll +++ b/python/ql/src/semmle/python/dataflow/Implementation.qll @@ -57,8 +57,8 @@ private newtype TAttributePath = * It might make sense to add another level, attribute of attribute. * But some experimentation would be needed. */ - TAttribute(string name) { exists(Attribute a | a.getName() = name) } + TAttribute(string name) { exists(Attribute a | a.getName() = name) } /** * The attribute of the tracked value holding the taint. @@ -445,9 +445,8 @@ class TaintTrackingImplementation extends string { context = TNoParam() and src = TTaintTrackingNode_(retval, TNoParam(), path, kind, this) and node.asCfgNode() = call and - retval.asCfgNode() = any(Return ret | ret.getScope() = pyfunc.getScope()) - .getValue() - .getAFlowNode() + retval.asCfgNode() = + any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode() ) and edgeLabel = "return" } @@ -469,9 +468,8 @@ class TaintTrackingImplementation extends string { this.callContexts(call, src, pyfunc, context, callee) and retnode = TTaintTrackingNode_(retval, callee, path, kind, this) and node.asCfgNode() = call and - retval.asCfgNode() = any(Return ret | ret.getScope() = pyfunc.getScope()) - .getValue() - .getAFlowNode() + retval.asCfgNode() = + any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode() ) and edgeLabel = "call" } @@ -717,7 +715,8 @@ private class EssaTaintTracking extends string { path.noAttribute() | assign.getValue().getAFlowNode() = srcnode.asCfgNode() and - kind = iterable_unpacking_descent(assign.getATarget().getAFlowNode(), defn.getDefiningNode(), + kind = + iterable_unpacking_descent(assign.getATarget().getAFlowNode(), defn.getDefiningNode(), srckind) ) } @@ -734,8 +733,8 @@ private class EssaTaintTracking extends string { then result = parent_kind else result = parent_kind.getMember() or - result = iterable_unpacking_descent(left_parent.getAnElement(), left_defn, - parent_kind.getMember()) + result = + iterable_unpacking_descent(left_parent.getAnElement(), left_defn, parent_kind.getMember()) } pragma[noinline] diff --git a/python/ql/src/semmle/python/dependencies/Dependencies.qll b/python/ql/src/semmle/python/dependencies/Dependencies.qll index bda3b45f323..6d2052f0dfb 100644 --- a/python/ql/src/semmle/python/dependencies/Dependencies.qll +++ b/python/ql/src/semmle/python/dependencies/Dependencies.qll @@ -1,13 +1,14 @@ - import python import semmle.python.dependencies.DependencyKind private predicate importDependency(Object target, AstNode source) { - source.getScope() != target.getOrigin() and /* Imports of own module are ignored */ + source.getScope() != target.getOrigin() and + /* Imports of own module are ignored */ ( exists(ModuleObject importee, ImportingStmt imp_stmt | source = imp_stmt and - importee = target | + importee = target + | exists(ImportMember im | imp_stmt.contains(im) | importee.importedAs(im.getImportedModuleName()) ) @@ -23,11 +24,9 @@ private predicate importDependency(Object target, AstNode source) { ) or /* from m import name, where m.name is not a submodule */ - exists(PythonModuleObject importee, ImportingStmt imp_stmt | - source = imp_stmt | + exists(PythonModuleObject importee, ImportingStmt imp_stmt | source = imp_stmt | exists(ImportMember im | imp_stmt.contains(im) | - importee.importedAs(im.getModule().(ImportExpr).getImportedModuleName()) - and + importee.importedAs(im.getModule().(ImportExpr).getImportedModuleName()) and defn_of_module_attribute(target, importee.getModule(), im.getName()) ) ) @@ -35,16 +34,12 @@ private predicate importDependency(Object target, AstNode source) { } class PythonImport extends DependencyKind { - - PythonImport() { - this = "import" - } + PythonImport() { this = "import" } override predicate isADependency(AstNode source, Object target) { this = this and importDependency(target, source) } - } private predicate interesting(Object target) { @@ -58,10 +53,7 @@ private predicate interesting(Object target) { } class PythonUse extends DependencyKind { - - PythonUse() { - this = "use" - } + PythonUse() { this = "use" } override predicate isADependency(AstNode source, Object target) { interesting(target) and @@ -71,22 +63,20 @@ class PythonUse extends DependencyKind { use.getNode() = source and use.refersTo(obj) and use.isLoad() - | + | interesting(obj) and target = obj - ) - and + ) and not has_more_specific_dependency_source(source) } - } -/** Whether there is a more specific dependency source than this one. +/** + * Whether there is a more specific dependency source than this one. * E.g. if the expression pack.mod.func is a dependency on the function 'func' in 'pack.mod' * don't make pack.mod depend on the module 'pack.mod' */ private predicate has_more_specific_dependency_source(Expr e) { - exists(Attribute member | - member.getObject() = e | + exists(Attribute member | member.getObject() = e | attribute_access_dependency(_, member) or has_more_specific_dependency_source(member) @@ -94,35 +84,25 @@ private predicate has_more_specific_dependency_source(Expr e) { } class PythonInheritance extends DependencyKind { - - PythonInheritance() { - this = "inheritance" - } + PythonInheritance() { this = "inheritance" } override predicate isADependency(AstNode source, Object target) { this = this and - exists(ClassObject cls | - source = cls.getOrigin() - | + exists(ClassObject cls | source = cls.getOrigin() | target = cls.getASuperType() or target = cls.getAnInferredType() ) } - } class PythonAttribute extends DependencyKind { - - PythonAttribute() { - this = "attribute" - } + PythonAttribute() { this = "attribute" } override predicate isADependency(AstNode source, Object target) { this = this and attribute_access_dependency(target, source) } - } private predicate attribute_access_dependency(Object target, AstNode source) { @@ -133,30 +113,23 @@ private predicate attribute_access_dependency(Object target, AstNode source) { } private predicate use_of_attribute(Attribute attr, Scope s, string name) { - exists(AttrNode cfg | - cfg.isLoad() and cfg.getNode() = attr - | - exists(Object obj | - cfg.getObject(name).refersTo(obj) | + exists(AttrNode cfg | cfg.isLoad() and cfg.getNode() = attr | + exists(Object obj | cfg.getObject(name).refersTo(obj) | s = obj.(PythonModuleObject).getModule() or s = obj.(ClassObject).getPyClass() - ) or - exists(ClassObject cls | - cfg.getObject(name).refersTo(_, cls, _) | - s = cls.getPyClass() ) + or + exists(ClassObject cls | cfg.getObject(name).refersTo(_, cls, _) | s = cls.getPyClass()) ) or - exists(SelfAttributeRead sar | - sar = attr | + exists(SelfAttributeRead sar | sar = attr | sar.getClass() = s and sar.getName() = name ) } private predicate defn_of_attribute(Object target, Scope s, string name) { - exists(Assign asgn | - target.(ControlFlowNode).getNode() = asgn | + exists(Assign asgn | target.(ControlFlowNode).getNode() = asgn | defn_of_instance_attribute(asgn, s, name) or defn_of_class_attribute(asgn, s, name) @@ -165,13 +138,14 @@ private predicate defn_of_attribute(Object target, Scope s, string name) { defn_of_module_attribute(target, s, name) } -/* Whether asgn defines an instance attribute, that is does +/* + * Whether asgn defines an instance attribute, that is does * asgn take the form self.name = ... where self is an instance * of class c and asgn is not a redefinition. */ + private predicate defn_of_instance_attribute(Assign asgn, Class c, string name) { - exists(SelfAttributeStore sas | - asgn.getATarget() = sas | + exists(SelfAttributeStore sas | asgn.getATarget() = sas | sas.getClass() = c and sas.getName() = name and not exists(SelfAttributeStore in_init | diff --git a/python/ql/src/semmle/python/dependencies/DependencyKind.qll b/python/ql/src/semmle/python/dependencies/DependencyKind.qll index 791723042ac..ae91593d251 100644 --- a/python/ql/src/semmle/python/dependencies/DependencyKind.qll +++ b/python/ql/src/semmle/python/dependencies/DependencyKind.qll @@ -3,7 +3,6 @@ import semmle.python.dependencies.Dependencies /** * A library describing an abstract mechanism for representing dependency categories. */ - /* * A DependencyCategory is a unique string key used by Architect to identify different categories * of dependencies that might be viewed independently. @@ -12,20 +11,17 @@ import semmle.python.dependencies.Dependencies * accepted by Architect. *

    */ -abstract class DependencyKind extends string { +abstract class DependencyKind extends string { bindingset[this] - DependencyKind() { - this = this - } + DependencyKind() { this = this } /* Tech inventory interface */ /** - * Identify dependencies associated with this category. - *

    - * The source element is the source of the dependency. - *

    - */ + * Identify dependencies associated with this category. + *

    + * The source element is the source of the dependency. + *

    + */ abstract predicate isADependency(AstNode source, Object target); - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/dependencies/TechInventory.qll b/python/ql/src/semmle/python/dependencies/TechInventory.qll index 8ca97f56178..43a7cf55ec2 100644 --- a/python/ql/src/semmle/python/dependencies/TechInventory.qll +++ b/python/ql/src/semmle/python/dependencies/TechInventory.qll @@ -2,49 +2,41 @@ import python import semmle.python.dependencies.Dependencies import semmle.python.dependencies.DependencyKind -/** Combine the source-file and package into a single string: +/** + * Combine the source-file and package into a single string: * /path/to/file.py<|>package-name-and-version */ string munge(File sourceFile, ExternalPackage package) { - result = "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>" + package.getVersion() or - not exists(package.getVersion()) and result = "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>unknown" + result = + "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>" + package.getVersion() + or + not exists(package.getVersion()) and + result = "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>unknown" } abstract class ExternalPackage extends Object { - - ExternalPackage() { - this instanceof ModuleObject - } + ExternalPackage() { this instanceof ModuleObject } abstract string getName(); abstract string getVersion(); - Object getAttribute(string name) { - result = this.(ModuleObject).attr(name) - } - - PackageObject getPackage() { - result = this.(ModuleObject).getPackage() - } + Object getAttribute(string name) { result = this.(ModuleObject).attr(name) } + PackageObject getPackage() { result = this.(ModuleObject).getPackage() } } bindingset[text] -private predicate is_version(string text) { - text.regexpMatch("\\d+\\.\\d+(\\.\\d+)?([ab]\\d+)?") -} +private predicate is_version(string text) { text.regexpMatch("\\d+\\.\\d+(\\.\\d+)?([ab]\\d+)?") } bindingset[v] private string version_format(float v) { - exists(int i, int f | - i = (v+0.05).floor() and f = ((v+0.05-i)*10).floor() | + exists(int i, int f | i = (v + 0.05).floor() and f = ((v + 0.05 - i) * 10).floor() | result = i + "." + f ) } class DistPackage extends ExternalPackage { - DistPackage() { exists(Folder parent | parent = this.(ModuleObject).getPath().getParent() and @@ -56,12 +48,13 @@ class DistPackage extends ExternalPackage { ) } - /* We don't extract the meta-data for dependencies (yet), so make a best guess from the source - * https://www.python.org/dev/peps/pep-0396/ + /* + * We don't extract the meta-data for dependencies (yet), so make a best guess from the source + * https://www.python.org/dev/peps/pep-0396/ */ + private predicate possibleVersion(string version, int priority) { - exists(Object v | - v = this.getAttribute("__version__") and priority = 3 | + exists(Object v | v = this.getAttribute("__version__") and priority = 3 | version = v.(StringObject).getText() and is_version(version) or version = version_format(v.(NumericObject).floatValue()) @@ -71,33 +64,36 @@ class DistPackage extends ExternalPackage { or exists(SequenceObject tuple, NumericObject major, NumericObject minor, string base_version | this.getAttribute("version_info") = tuple and - major = tuple.getInferredElement(0) and minor = tuple.getInferredElement(1) and - base_version = major.intValue() + "." + minor.intValue() | + major = tuple.getInferredElement(0) and + minor = tuple.getInferredElement(1) and + base_version = major.intValue() + "." + minor.intValue() + | version = base_version + "." + tuple.getBuiltinElement(2).(NumericObject).intValue() or not exists(tuple.getBuiltinElement(2)) and version = base_version - ) and priority = 2 + ) and + priority = 2 or - exists(string v | - v.toLowerCase() = "version" | + exists(string v | v.toLowerCase() = "version" | is_version(version) and version = this.getAttribute(v).(StringObject).getText() - ) and priority = 1 + ) and + priority = 1 } override string getVersion() { this.possibleVersion(result, max(int priority | this.possibleVersion(_, priority))) } - override string getName() { - result = this.(ModuleObject).getShortName() - } + override string getName() { result = this.(ModuleObject).getShortName() } predicate fromSource(Object src) { exists(ModuleObject m | m.getModule() = src.(ControlFlowNode).getEnclosingModule() or - src = m | - m = this or + src = m + | + m = this + or m.getPackage+() = this and not exists(DistPackage inter | m.getPackage*() = inter and @@ -105,12 +101,10 @@ class DistPackage extends ExternalPackage { ) ) } - } predicate dependency(AstNode src, DistPackage package) { - exists(DependencyKind cat, Object target | - cat.isADependency(src, target) | + exists(DependencyKind cat, Object target | cat.isADependency(src, target) | package.fromSource(target) ) } diff --git a/python/ql/src/semmle/python/essa/Definitions.qll b/python/ql/src/semmle/python/essa/Definitions.qll index c21e8148582..6ecb3f6b50d 100644 --- a/python/ql/src/semmle/python/essa/Definitions.qll +++ b/python/ql/src/semmle/python/essa/Definitions.qll @@ -1,6 +1,7 @@ import python -/* Classification of variables. These should be non-overlapping and complete. +/* + * Classification of variables. These should be non-overlapping and complete. * * Function local variables - Non escaping variables in a function, except 'self' * Self variables - The 'self' variable for a method. @@ -11,31 +12,24 @@ import python * Escaping globals -- Global variables that have definitions and at least one of those definitions is in another scope. */ - /** A source language variable, to be converted into a set of SSA variables. */ +/** A source language variable, to be converted into a set of SSA variables. */ abstract class SsaSourceVariable extends @py_variable { - SsaSourceVariable() { /* Exclude `True`, `False` and `None` */ not this.(Variable).getALoad() instanceof NameConstant } /** Gets the name of this variable */ - string getName() { - variable(this, _, result) - } + string getName() { variable(this, _, result) } - Scope getScope() { - variable(this, result, _) - } + Scope getScope() { variable(this, result, _) } /** Gets an implicit use of this variable */ abstract ControlFlowNode getAnImplicitUse(); abstract ControlFlowNode getScopeEntryDefinition(); - string toString() { - result = "SsaSourceVariable " + this.getName() - } + string toString() { result = "SsaSourceVariable " + this.getName() } /** Gets a use of this variable, either explicit or implicit. */ ControlFlowNode getAUse() { @@ -43,14 +37,18 @@ abstract class SsaSourceVariable extends @py_variable { or result = this.getAnImplicitUse() or - /* `import *` is a definition of *all* variables, so must be a use as well, for pass-through + /* + * `import *` is a definition of *all* variables, so must be a use as well, for pass-through * once we have established that a variable is not redefined. */ + SsaSource::import_star_refinement(this, result, _) or - /* Add a use at the end of scope for all variables to keep them live + /* + * Add a use at the end of scope for all variables to keep them live * This is necessary for taint-tracking. */ + result = this.getScope().getANormalExit() } @@ -73,15 +71,18 @@ abstract class SsaSourceVariable extends @py_variable { SsaSource::with_definition(this, def) } - /** Holds if `def` defines an ESSA variable for this variable in such a way + /** + * Holds if `def` defines an ESSA variable for this variable in such a way * that the new variable is a refinement in some way of the variable used at `use`. */ predicate hasRefinement(ControlFlowNode use, ControlFlowNode def) { - this.hasDefiningNode(_) and /* Can't have a refinement unless there is a definition */ + this.hasDefiningNode(_) and + /* Can't have a refinement unless there is a definition */ refinement(this, use, def) } - /** Holds if the edge `pred`->`succ` defines an ESSA variable for this variable in such a way + /** + * Holds if the edge `pred`->`succ` defines an ESSA variable for this variable in such a way * that the new variable is a refinement in some way of the variable used at `use`. */ predicate hasRefinementEdge(ControlFlowNode use, BasicBlock pred, BasicBlock succ) { @@ -100,7 +101,6 @@ abstract class SsaSourceVariable extends @py_variable { } abstract CallNode redefinedAtCallSite(); - } private predicate refinement(SsaSourceVariable v, ControlFlowNode use, ControlFlowNode def) { @@ -119,9 +119,7 @@ private predicate refinement(SsaSourceVariable v, ControlFlowNode use, ControlFl def = v.redefinedAtCallSite() and def = use } - class FunctionLocalVariable extends SsaSourceVariable { - FunctionLocalVariable() { this.(LocalVariable).getScope() instanceof Function and not this instanceof NonLocalVariable @@ -132,8 +130,7 @@ class FunctionLocalVariable extends SsaSourceVariable { } override ControlFlowNode getScopeEntryDefinition() { - exists(Scope s | - s.getEntryNode() = result | + exists(Scope s | s.getEntryNode() = result | s = this.(LocalVariable).getScope() and not this.(LocalVariable).isParameter() or @@ -143,11 +140,9 @@ class FunctionLocalVariable extends SsaSourceVariable { } override CallNode redefinedAtCallSite() { none() } - } class NonLocalVariable extends SsaSourceVariable { - NonLocalVariable() { exists(Function f | this.(LocalVariable).getScope() = f and @@ -169,37 +164,27 @@ class NonLocalVariable extends SsaSourceVariable { this.(LocalVariable).getScope().getEntryNode() = result } - pragma [noinline] - Scope scope_as_local_variable() { - result = this.(LocalVariable).getScope() - } + pragma[noinline] + Scope scope_as_local_variable() { result = this.(LocalVariable).getScope() } override CallNode redefinedAtCallSite() { result.getScope().getScope*() = this.scope_as_local_variable() } - } class ClassLocalVariable extends SsaSourceVariable { + ClassLocalVariable() { this.(LocalVariable).getScope() instanceof Class } - ClassLocalVariable() { - this.(LocalVariable).getScope() instanceof Class - } - - override ControlFlowNode getAnImplicitUse() { - none() - } + override ControlFlowNode getAnImplicitUse() { none() } override ControlFlowNode getScopeEntryDefinition() { result = this.(LocalVariable).getScope().getEntryNode() } override CallNode redefinedAtCallSite() { none() } - } class BuiltinVariable extends SsaSourceVariable { - BuiltinVariable() { this instanceof GlobalVariable and not exists(this.(Variable).getAStore()) and @@ -208,20 +193,14 @@ class BuiltinVariable extends SsaSourceVariable { not exists(ImportStar is | is.getScope() = this.(Variable).getScope()) } - override ControlFlowNode getAnImplicitUse() { - none() - } + override ControlFlowNode getAnImplicitUse() { none() } - override ControlFlowNode getScopeEntryDefinition() { - none() - } + override ControlFlowNode getScopeEntryDefinition() { none() } override CallNode redefinedAtCallSite() { none() } - } class ModuleVariable extends SsaSourceVariable { - ModuleVariable() { this instanceof GlobalVariable and ( @@ -235,10 +214,8 @@ class ModuleVariable extends SsaSourceVariable { ) } - pragma [noinline] - CallNode global_variable_callnode() { - result.getScope() = this.(GlobalVariable).getScope() - } + pragma[noinline] + CallNode global_variable_callnode() { result.getScope() = this.(GlobalVariable).getScope() } pragma[noinline] ImportMemberNode global_variable_import() { @@ -251,8 +228,7 @@ class ModuleVariable extends SsaSourceVariable { or result = global_variable_import() or - exists(ImportTimeScope scope | - scope.entryEdge(result, _) | + exists(ImportTimeScope scope | scope.entryEdge(result, _) | this = scope.getOuterVariable(_) or this.(Variable).getAUse().getScope() = scope ) @@ -264,14 +240,14 @@ class ModuleVariable extends SsaSourceVariable { ) or exists(ImportTimeScope s | - result = s.getANormalExit() and this.(Variable).getScope() = s and + result = s.getANormalExit() and + this.(Variable).getScope() = s and implicit_definition(this) ) } override ControlFlowNode getScopeEntryDefinition() { - exists(Scope s | - s.getEntryNode() = result | + exists(Scope s | s.getEntryNode() = result | /* Module entry point */ this.(GlobalVariable).getScope() = s or @@ -282,31 +258,28 @@ class ModuleVariable extends SsaSourceVariable { this.(GlobalVariable).getAUse().getScope() = s ) or - exists(ImportTimeScope scope | - scope.entryEdge(_, result) | + exists(ImportTimeScope scope | scope.entryEdge(_, result) | this = scope.getOuterVariable(_) or this.(Variable).getAUse().getScope() = scope ) } override CallNode redefinedAtCallSite() { none() } - } class NonEscapingGlobalVariable extends ModuleVariable { - NonEscapingGlobalVariable() { this instanceof GlobalVariable and exists(this.(Variable).getAStore()) and not variable_or_attribute_defined_out_of_scope(this) } - } class EscapingGlobalVariable extends ModuleVariable { - EscapingGlobalVariable() { - this instanceof GlobalVariable and exists(this.(Variable).getAStore()) and variable_or_attribute_defined_out_of_scope(this) + this instanceof GlobalVariable and + exists(this.(Variable).getAStore()) and + variable_or_attribute_defined_out_of_scope(this) } override ControlFlowNode getAnImplicitUse() { @@ -328,36 +301,25 @@ class EscapingGlobalVariable extends ModuleVariable { result = this.innerScope().getEntryNode() } - pragma [noinline] - Scope scope_as_global_variable() { - result = this.(GlobalVariable).getScope() - } + pragma[noinline] + Scope scope_as_global_variable() { result = this.(GlobalVariable).getScope() } override CallNode redefinedAtCallSite() { result.(CallNode).getScope().getScope*() = this.scope_as_global_variable() } - } class EscapingAssignmentGlobalVariable extends EscapingGlobalVariable { - EscapingAssignmentGlobalVariable() { exists(NameNode n | n.defines(this) and not n.getScope() = this.getScope()) } - } - class SpecialSsaSourceVariable extends SsaSourceVariable { - - SpecialSsaSourceVariable() { - variable(this, _, "*") or variable(this, _, "$") - } + SpecialSsaSourceVariable() { variable(this, _, "*") or variable(this, _, "$") } override ControlFlowNode getAnImplicitUse() { - exists(ImportTimeScope s | - result = s.getANormalExit() and this.getScope() = s - ) + exists(ImportTimeScope s | result = s.getANormalExit() and this.getScope() = s) } override ControlFlowNode getScopeEntryDefinition() { @@ -365,31 +327,31 @@ class SpecialSsaSourceVariable extends SsaSourceVariable { this.getScope().getEntryNode() = result } - pragma [noinline] - Scope scope_as_global_variable() { - result = this.(GlobalVariable).getScope() - } + pragma[noinline] + Scope scope_as_global_variable() { result = this.(GlobalVariable).getScope() } override CallNode redefinedAtCallSite() { result.(CallNode).getScope().getScope*() = this.scope_as_global_variable() } - } /** Holds if this variable is implicitly defined */ private predicate implicit_definition(Variable v) { - v.getId() = "*" or v.getId() = "$" - or + v.getId() = "*" or + v.getId() = "$" or exists(ImportStar is | is.getScope() = v.getScope()) } private predicate variable_or_attribute_defined_out_of_scope(Variable v) { exists(NameNode n | n.defines(v) and not n.getScope() = v.getScope()) or - exists(AttrNode a | a.isStore() and a.getObject() = v.getAUse() and not a.getScope() = v.getScope()) + exists(AttrNode a | + a.isStore() and a.getObject() = v.getAUse() and not a.getScope() = v.getScope() + ) } private predicate class_with_global_metaclass(Class cls, GlobalVariable metaclass) { - metaclass.getId() = "__metaclass__" and major_version() = 2 and + metaclass.getId() = "__metaclass__" and + major_version() = 2 and cls.getEnclosingModule() = metaclass.getScope() } diff --git a/python/ql/src/semmle/python/essa/Essa.qll b/python/ql/src/semmle/python/essa/Essa.qll index fdfc2fb92fe..4608499be46 100644 --- a/python/ql/src/semmle/python/essa/Essa.qll +++ b/python/ql/src/semmle/python/essa/Essa.qll @@ -6,46 +6,35 @@ import python private import SsaCompute import semmle.python.essa.Definitions - /** An (enhanced) SSA variable derived from `SsaSourceVariable`. */ class EssaVariable extends TEssaDefinition { - /** Gets the (unique) definition of this variable. */ - EssaDefinition getDefinition() { - this = result - } + EssaDefinition getDefinition() { this = result } - /** Gets a use of this variable, where a "use" is defined by + /** + * Gets a use of this variable, where a "use" is defined by * `SsaSourceVariable.getAUse()`. * Note that this differs from `EssaVariable.getASourceUse()`. */ - ControlFlowNode getAUse() { - result = this.getDefinition().getAUse() - } + ControlFlowNode getAUse() { result = this.getDefinition().getAUse() } /** Gets the source variable from which this variable is derived. */ - SsaSourceVariable getSourceVariable() { - result = this.getDefinition().getSourceVariable() - } + SsaSourceVariable getSourceVariable() { result = this.getDefinition().getSourceVariable() } /** Gets the name of this variable. */ - string getName() { - result = this.getSourceVariable().getName() - } + string getName() { result = this.getSourceVariable().getName() } - string toString() { - result = "SSA variable " + this.getName() - } + string toString() { result = "SSA variable " + this.getName() } - /** Gets a string representation of this variable. + /** + * Gets a string representation of this variable. * WARNING: The format of this may change and it may be very inefficient to compute. * To used for debugging and testing only. */ - string getRepresentation() { - result = this.getSourceVariable().getName() + "_" + var_rank(this) - } + string getRepresentation() { result = this.getSourceVariable().getName() + "_" + var_rank(this) } - /** Gets a use of this variable, where a "use" is defined by + /** + * Gets a use of this variable, where a "use" is defined by * `SsaSourceVariable.getASourceUse()`. * Note that this differs from `EssaVariable.getAUse()`. */ @@ -63,23 +52,21 @@ class EssaVariable extends TEssaDefinition { } /** Gets the scope of this variable. */ - Scope getScope() { - result = this.getDefinition().getScope() - } + Scope getScope() { result = this.getDefinition().getScope() } - /** Holds if this the meta-variable for a scope. + /** + * Holds if this the meta-variable for a scope. * This is used to attach attributes for undeclared variables implicitly * defined by `from ... import *` and the like. */ - predicate isMetaVariable() { - this.getName() = "$" - } - + predicate isMetaVariable() { this.getName() = "$" } } -/* Helper for location_string +/* + * Helper for location_string * NOTE: This is Python specific, to make `getRepresentation()` portable will require further work. */ + private int exception_handling(BasicBlock b) { b.reachesExit() and result = 0 or @@ -91,14 +78,15 @@ pragma[noinline] private string location_string(EssaVariable v) { exists(EssaDefinition def, BasicBlock b, int index, int line, int col | def = v.getDefinition() and - (if b.getNode(0).isNormalExit() then - line = 100000 and col = 0 - else - b.hasLocationInfo(_, line, col, _, _) + ( + if b.getNode(0).isNormalExit() + then line = 100000 and col = 0 + else b.hasLocationInfo(_, line, col, _, _) ) and /* Add large numbers to values to prevent 1000 sorting before 99 */ - result = (line + 100000) + ":" + (col*2 + 10000 + exception_handling(b)) + ":" + (index + 100003) - | + result = + (line + 100000) + ":" + (col * 2 + 10000 + exception_handling(b)) + ":" + (index + 100003) + | def = TEssaNodeDefinition(_, b, index) or def = TEssaNodeRefinement(_, b, index) @@ -119,37 +107,31 @@ private int var_rank(EssaVariable v) { exists(int r, SsaSourceVariable var | var = v.getSourceVariable() and var_index(v) = rank[r](EssaVariable x | x.getSourceVariable() = var | var_index(x)) and - result = r-1 + result = r - 1 ) } /** Underlying IPA type for EssaDefinition and EssaVariable. */ -private cached newtype TEssaDefinition = +cached +private newtype TEssaDefinition = TEssaNodeDefinition(SsaSourceVariable v, BasicBlock b, int i) { EssaDefinitions::variableDefinition(v, _, b, _, i) - } - or + } or TEssaNodeRefinement(SsaSourceVariable v, BasicBlock b, int i) { EssaDefinitions::variableRefinement(v, _, b, _, i) - } - or + } or TEssaEdgeDefinition(SsaSourceVariable v, BasicBlock pred, BasicBlock succ) { EssaDefinitions::piNode(v, pred, succ) - } - or - TPhiFunction(SsaSourceVariable v, BasicBlock b) { - EssaDefinitions::phiNode(v, b) - } + } or + TPhiFunction(SsaSourceVariable v, BasicBlock b) { EssaDefinitions::phiNode(v, b) } -/** Definition of an extended-SSA (ESSA) variable. +/** + * Definition of an extended-SSA (ESSA) variable. * There is exactly one definition for each variable, * and exactly one variable for each definition. */ abstract class EssaDefinition extends TEssaDefinition { - - string toString() { - result = "EssaDefinition" - } + string toString() { result = "EssaDefinition" } /** Gets the source variable for which this a definition, either explicit or implicit. */ abstract SsaSourceVariable getSourceVariable(); @@ -160,7 +142,8 @@ abstract class EssaDefinition extends TEssaDefinition { /** Holds if this definition reaches the end of `b`. */ abstract predicate reachesEndOfBlock(BasicBlock b); - /** Gets the location of a control flow node that is indicative of this definition. + /** + * Gets the location of a control flow node that is indicative of this definition. * Since definitions may occur on edges of the control flow graph, the given location may * be imprecise. * Distinct `EssaDefinitions` may return the same ControlFlowNode even for @@ -168,29 +151,26 @@ abstract class EssaDefinition extends TEssaDefinition { */ abstract Location getLocation(); - /** Gets a representation of this SSA definition for debugging purposes. - * Since this is primarily for debugging and testing, performance may be poor. */ + /** + * Gets a representation of this SSA definition for debugging purposes. + * Since this is primarily for debugging and testing, performance may be poor. + */ abstract string getRepresentation(); abstract Scope getScope(); - EssaVariable getVariable() { - result.getDefinition() = this - } + EssaVariable getVariable() { result.getDefinition() = this } abstract BasicBlock getBasicBlock(); - } -/** An ESSA definition corresponding to an edge refinement of the underlying variable. +/** + * An ESSA definition corresponding to an edge refinement of the underlying variable. * For example, the edges leaving a test on a variable both represent refinements of that * variable. On one edge the test is true, on the other it is false. */ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { - - override string toString() { - result = "SSA filter definition" - } + override string toString() { result = "SSA filter definition" } boolean getSense() { this.getPredecessor().getATrueSuccessor() = this.getSuccessor() and result = true @@ -198,19 +178,13 @@ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { this.getPredecessor().getAFalseSuccessor() = this.getSuccessor() and result = false } - override SsaSourceVariable getSourceVariable() { - this = TEssaEdgeDefinition(result, _, _) - } + override SsaSourceVariable getSourceVariable() { this = TEssaEdgeDefinition(result, _, _) } /** Gets the basic block preceding the edge on which this refinement occurs. */ - BasicBlock getPredecessor() { - this = TEssaEdgeDefinition(_, result, _) - } + BasicBlock getPredecessor() { this = TEssaEdgeDefinition(_, result, _) } /** Gets the basic block succeeding the edge on which this refinement occurs. */ - BasicBlock getSuccessor() { - this = TEssaEdgeDefinition(_, _, result) - } + BasicBlock getSuccessor() { this = TEssaEdgeDefinition(_, _, result) } override ControlFlowNode getAUse() { SsaDefinitions::reachesUse(this.getSourceVariable(), this.getSuccessor(), piIndex(), result) @@ -220,13 +194,11 @@ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { SsaDefinitions::reachesEndOfBlock(this.getSourceVariable(), this.getSuccessor(), piIndex(), b) } - override Location getLocation() { - result = this.getSuccessor().getNode(0).getLocation() - } + override Location getLocation() { result = this.getSuccessor().getNode(0).getLocation() } /** Gets the SSA variable to which this refinement applies. */ EssaVariable getInput() { - exists(SsaSourceVariable var , EssaDefinition def | + exists(SsaSourceVariable var, EssaDefinition def | var = this.getSourceVariable() and var = def.getSourceVariable() and def.reachesEndOfBlock(this.getPredecessor()) and @@ -239,19 +211,13 @@ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { } /** Gets the scope of the variable defined by this definition. */ - override Scope getScope() { - result = this.getPredecessor().getScope() - } - - override BasicBlock getBasicBlock(){ - result = this.getSuccessor() - } + override Scope getScope() { result = this.getPredecessor().getScope() } + override BasicBlock getBasicBlock() { result = this.getSuccessor() } } /** A Phi-function as specified in classic SSA form. */ class PhiFunction extends EssaDefinition, TPhiFunction { - override ControlFlowNode getAUse() { SsaDefinitions::reachesUse(this.getSourceVariable(), this.getBasicBlock(), phiIndex(), result) } @@ -260,9 +226,7 @@ class PhiFunction extends EssaDefinition, TPhiFunction { SsaDefinitions::reachesEndOfBlock(this.getSourceVariable(), this.getBasicBlock(), phiIndex(), b) } - override SsaSourceVariable getSourceVariable() { - this = TPhiFunction(result, _) - } + override SsaSourceVariable getSourceVariable() { this = TPhiFunction(result, _) } /** Gets an input refinement that exists on one of the incoming edges to this phi node. */ private EssaEdgeRefinement inputEdgeRefinement(BasicBlock pred) { @@ -290,37 +254,29 @@ class PhiFunction extends EssaDefinition, TPhiFunction { } /** Gets the input variable for this phi node on the edge `pred` -> `this.getBasicBlock()`, if any. */ - cached EssaVariable getInput(BasicBlock pred) { + cached + EssaVariable getInput(BasicBlock pred) { result.getDefinition() = this.reachingDefinition(pred) or result.getDefinition() = this.inputEdgeRefinement(pred) } /** Gets an input variable for this phi node. */ - EssaVariable getAnInput() { - result = this.getInput(_) - } + EssaVariable getAnInput() { result = this.getInput(_) } /** Holds if forall incoming edges in the flow graph, there is an input variable */ predicate isComplete() { - forall(BasicBlock pred | - pred = this.getBasicBlock().getAPredecessor() | + forall(BasicBlock pred | pred = this.getBasicBlock().getAPredecessor() | exists(this.getInput(pred)) ) } - override string toString() { - result = "SSA Phi Function" - } + override string toString() { result = "SSA Phi Function" } /** Gets the basic block that succeeds this phi node. */ - override BasicBlock getBasicBlock() { - this = TPhiFunction(_, result) - } + override BasicBlock getBasicBlock() { this = TPhiFunction(_, result) } - override Location getLocation() { - result = this.getBasicBlock().getNode(0).getLocation() - } + override Location getLocation() { result = this.getBasicBlock().getNode(0).getLocation() } /** Helper for `argList(n)`. */ private int rankInput(EssaVariable input) { @@ -330,12 +286,10 @@ class PhiFunction extends EssaDefinition, TPhiFunction { /** Helper for `argList()`. */ private string argList(int n) { - exists(EssaVariable input | - n = this.rankInput(input) - | + exists(EssaVariable input | n = this.rankInput(input) | n = 1 and result = input.getRepresentation() or - n > 1 and result = this.argList(n-1) + ", " + input.getRepresentation() + n > 1 and result = this.argList(n - 1) + ", " + input.getRepresentation() ) } @@ -352,13 +306,12 @@ class PhiFunction extends EssaDefinition, TPhiFunction { or result = "phi(" + this.argList() + ")" or - exists(this.getAnInput()) and not exists(this.argList()) and + exists(this.getAnInput()) and + not exists(this.argList()) and result = "phi(" + this.getSourceVariable().getName() + "??)" } - override Scope getScope() { - result = this.getBasicBlock().getScope() - } + override Scope getScope() { result = this.getBasicBlock().getScope() } private EssaEdgeRefinement piInputDefinition(EssaVariable input) { input = this.getAnInput() and @@ -367,7 +320,8 @@ class PhiFunction extends EssaDefinition, TPhiFunction { input = this.getAnInput() and result = input.getDefinition().(PhiFunction).piInputDefinition(_) } - /** Gets the variable which is the common and complete input to all pi-nodes that are themselves + /** + * Gets the variable which is the common and complete input to all pi-nodes that are themselves * inputs to this phi-node. * For example: * ``` @@ -387,19 +341,15 @@ class PhiFunction extends EssaDefinition, TPhiFunction { * meaning that we cannot track `x` from `x0` to `x3`. * By using `getShortCircuitInput()` we can do so, since the short-circuit input of `x3` is `x0`. */ - pragma [noinline] + pragma[noinline] EssaVariable getShortCircuitInput() { exists(BasicBlock common | - forall(EssaVariable input | - input = this.getAnInput() | + forall(EssaVariable input | input = this.getAnInput() | common = this.piInputDefinition(input).getPredecessor() - ) - and - forall(BasicBlock succ | - succ = common.getASuccessor() | + ) and + forall(BasicBlock succ | succ = common.getASuccessor() | succ = this.piInputDefinition(_).getSuccessor() - ) - and + ) and exists(EssaEdgeRefinement ref | ref = this.piInputDefinition(_) and ref.getPredecessor() = common and @@ -409,14 +359,12 @@ class PhiFunction extends EssaDefinition, TPhiFunction { } } -/** A definition of an ESSA variable that is not directly linked to +/** + * A definition of an ESSA variable that is not directly linked to * another ESSA variable. */ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition { - - override string toString() { - result = "Essa node definition" - } + override string toString() { result = "Essa node definition" } override ControlFlowNode getAUse() { exists(SsaSourceVariable v, BasicBlock b, int i | @@ -432,22 +380,14 @@ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition { ) } - override SsaSourceVariable getSourceVariable() { - this = TEssaNodeDefinition(result, _, _) - } + override SsaSourceVariable getSourceVariable() { this = TEssaNodeDefinition(result, _, _) } /** Gets the ControlFlowNode corresponding to this definition */ - ControlFlowNode getDefiningNode() { - this.definedBy(_, result) - } + ControlFlowNode getDefiningNode() { this.definedBy(_, result) } - override Location getLocation() { - result = this.getDefiningNode().getLocation() - } + override Location getLocation() { result = this.getDefiningNode().getLocation() } - override string getRepresentation() { - result = this.getAQlClass() - } + override string getRepresentation() { result = this.getAQlClass() } override Scope getScope() { exists(BasicBlock defb | @@ -457,26 +397,19 @@ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition { } predicate definedBy(SsaSourceVariable v, ControlFlowNode def) { - exists(BasicBlock b, int i | - def = b.getNode(i) | - this = TEssaNodeDefinition(v, b, i+i) + exists(BasicBlock b, int i | def = b.getNode(i) | + this = TEssaNodeDefinition(v, b, i + i) or - this = TEssaNodeDefinition(v, b, i+i+1) + this = TEssaNodeDefinition(v, b, i + i + 1) ) } - override BasicBlock getBasicBlock(){ - result = this.getDefiningNode().getBasicBlock() - } - + override BasicBlock getBasicBlock() { result = this.getDefiningNode().getBasicBlock() } } /** A definition of an ESSA variable that takes another ESSA variable as an input. */ class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement { - - override string toString() { - result = "SSA filter definition" - } + override string toString() { result = "SSA filter definition" } /** Gets the SSA variable to which this refinement applies. */ EssaVariable getInput() { @@ -498,18 +431,12 @@ class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement { ) } - override SsaSourceVariable getSourceVariable() { - this = TEssaNodeRefinement(result, _, _) - } + override SsaSourceVariable getSourceVariable() { this = TEssaNodeRefinement(result, _, _) } /** Gets the ControlFlowNode corresponding to this definition */ - ControlFlowNode getDefiningNode() { - this.definedBy(_, result) - } + ControlFlowNode getDefiningNode() { this.definedBy(_, result) } - override Location getLocation() { - result = this.getDefiningNode().getLocation() - } + override Location getLocation() { result = this.getDefiningNode().getLocation() } override string getRepresentation() { result = this.getAQlClass() + "(" + this.getInput().getRepresentation() + ")" @@ -526,23 +453,19 @@ class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement { } predicate definedBy(SsaSourceVariable v, ControlFlowNode def) { - exists(BasicBlock b, int i | - def = b.getNode(i) | - this = TEssaNodeRefinement(v, b, i+i) + exists(BasicBlock b, int i | def = b.getNode(i) | + this = TEssaNodeRefinement(v, b, i + i) or - this = TEssaNodeRefinement(v, b, i+i+1) + this = TEssaNodeRefinement(v, b, i + i + 1) ) } - override BasicBlock getBasicBlock(){ - result = this.getDefiningNode().getBasicBlock() - } - + override BasicBlock getBasicBlock() { result = this.getDefiningNode().getBasicBlock() } } pragma[noopt] private EssaVariable potential_input(EssaNodeRefinement ref) { - exists(ControlFlowNode use, SsaSourceVariable var, ControlFlowNode def | + exists(ControlFlowNode use, SsaSourceVariable var, ControlFlowNode def | var.hasRefinement(use, def) and use = result.getAUse() and var = result.getSourceVariable() and @@ -559,7 +482,6 @@ deprecated class PyNodeRefinement = EssaNodeRefinement; /** An assignment to a variable `v = val` */ class AssignmentDefinition extends EssaNodeDefinition { - AssignmentDefinition() { SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _) } @@ -568,15 +490,11 @@ class AssignmentDefinition extends EssaNodeDefinition { SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), result) } - override string getRepresentation() { - result = this.getValue().getNode().toString() - } - + override string getRepresentation() { result = this.getValue().getNode().toString() } } /** Capture of a raised exception `except ExceptionType ex:` */ -class ExceptionCapture extends EssaNodeDefinition { - +class ExceptionCapture extends EssaNodeDefinition { ExceptionCapture() { SsaSource::exception_capture(this.getSourceVariable(), this.getDefiningNode()) } @@ -588,15 +506,11 @@ class ExceptionCapture extends EssaNodeDefinition { ) } - override string getRepresentation() { - result = "except " + this.getSourceVariable().getName() - } - + override string getRepresentation() { result = "except " + this.getSourceVariable().getName() } } /** An assignment to a variable as part of a multiple assignment `..., v, ... = val` */ class MultiAssignmentDefinition extends EssaNodeDefinition { - MultiAssignmentDefinition() { SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _, _) } @@ -610,130 +524,99 @@ class MultiAssignmentDefinition extends EssaNodeDefinition { /** Holds if `this` has (zero-based) index `index` in `lhs`. */ predicate indexOf(int index, SequenceNode lhs) { - SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), index, lhs) + SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), index, + lhs) } - - } /** A definition of a variable in a `with` statement */ class WithDefinition extends EssaNodeDefinition { + WithDefinition() { SsaSource::with_definition(this.getSourceVariable(), this.getDefiningNode()) } - WithDefinition () { - SsaSource::with_definition(this.getSourceVariable(), this.getDefiningNode()) - } - - override string getRepresentation() { - result = "with" - } - + override string getRepresentation() { result = "with" } } /** A definition of a variable by declaring it as a parameter */ class ParameterDefinition extends EssaNodeDefinition { - ParameterDefinition() { SsaSource::parameter_definition(this.getSourceVariable(), this.getDefiningNode()) } - predicate isSelf() { - this.getDefiningNode().getNode().(Parameter).isSelf() - } + predicate isSelf() { this.getDefiningNode().getNode().(Parameter).isSelf() } /** Gets the control flow node for the default value of this parameter */ - ControlFlowNode getDefault() { - result.getNode() = this.getParameter().getDefault() - } + ControlFlowNode getDefault() { result.getNode() = this.getParameter().getDefault() } /** Gets the annotation control flow node of this parameter */ - ControlFlowNode getAnnotation() { - result.getNode() = this.getParameter().getAnnotation() - } + ControlFlowNode getAnnotation() { result.getNode() = this.getParameter().getAnnotation() } /** Gets the name of this parameter definition */ - string getName() { - result = this.getParameter().asName().getId() - } + string getName() { result = this.getParameter().asName().getId() } predicate isVarargs() { exists(Function func | func.getVararg() = this.getDefiningNode().getNode()) } - /** Holds if this parameter is a 'kwargs' parameter. + /** + * Holds if this parameter is a 'kwargs' parameter. * The `kwargs` in `f(a, b, **kwargs)`. */ predicate isKwargs() { exists(Function func | func.getKwarg() = this.getDefiningNode().getNode()) } - Parameter getParameter() { - result = this.getDefiningNode().getNode() - } - + Parameter getParameter() { result = this.getDefiningNode().getNode() } } - /** A deletion of a variable `del v` */ class DeletionDefinition extends EssaNodeDefinition { - DeletionDefinition() { SsaSource::deletion_definition(this.getSourceVariable(), this.getDefiningNode()) } - } -/** Definition of variable at the entry of a scope. Usually this represents the transfer of +/** + * Definition of variable at the entry of a scope. Usually this represents the transfer of * a global or non-local variable from one scope to another. */ class ScopeEntryDefinition extends EssaNodeDefinition { - ScopeEntryDefinition() { this.getDefiningNode() = this.getSourceVariable().getScopeEntryDefinition() and not this instanceof ImplicitSubModuleDefinition } - override Scope getScope() { - result.getEntryNode() = this.getDefiningNode() - } - + override Scope getScope() { result.getEntryNode() = this.getDefiningNode() } } /** Possible redefinition of variable via `from ... import *` */ class ImportStarRefinement extends EssaNodeRefinement { - ImportStarRefinement() { SsaSource::import_star_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } - } /** Assignment of an attribute `obj.attr = val` */ class AttributeAssignment extends EssaNodeRefinement { - AttributeAssignment() { SsaSource::attribute_assignment_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } - string getName() { - result = this.getDefiningNode().(AttrNode).getName() - } + string getName() { result = this.getDefiningNode().(AttrNode).getName() } - ControlFlowNode getValue() { - result = this.getDefiningNode().(DefinitionNode).getValue() - } + ControlFlowNode getValue() { result = this.getDefiningNode().(DefinitionNode).getValue() } override string getRepresentation() { - result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getInput().getRepresentation() + ")" + result = + this.getAQlClass() + " '" + this.getName() + "'(" + this.getInput().getRepresentation() + ")" or not exists(this.getInput()) and - result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getSourceVariable().getName() + "??)" + result = + this.getAQlClass() + " '" + this.getName() + "'(" + this.getSourceVariable().getName() + "??)" } - } /** A use of a variable as an argument, `foo(v)`, which might modify the object referred to. */ class ArgumentRefinement extends EssaNodeRefinement { - ControlFlowNode argument; ArgumentRefinement() { @@ -747,20 +630,15 @@ class ArgumentRefinement extends EssaNodeRefinement { /** Deletion of an attribute `del obj.attr`. */ class EssaAttributeDeletion extends EssaNodeRefinement { - EssaAttributeDeletion() { SsaSource::attribute_deletion_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } - string getName() { - result = this.getDefiningNode().(AttrNode).getName() - } - + string getName() { result = this.getDefiningNode().(AttrNode).getName() } } /** A pi-node (guard) with only one successor. */ class SingleSuccessorGuard extends EssaNodeRefinement { - SingleSuccessorGuard() { SsaSource::test_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } @@ -778,35 +656,28 @@ class SingleSuccessorGuard extends EssaNodeRefinement { result = EssaNodeRefinement.super.getRepresentation() + " [??]" } - ControlFlowNode getTest() { - result = this.getDefiningNode() - } + ControlFlowNode getTest() { result = this.getDefiningNode() } predicate useAndTest(ControlFlowNode use, ControlFlowNode test) { test = this.getDefiningNode() and SsaSource::test_refinement(this.getSourceVariable(), use, test) } - } -/** Implicit definition of the names of sub-modules in a package. +/** + * Implicit definition of the names of sub-modules in a package. * Although the interpreter does not pre-define these names, merely populating them * as they are imported, this is a good approximation for static analysis. */ class ImplicitSubModuleDefinition extends EssaNodeDefinition { - ImplicitSubModuleDefinition() { SsaSource::init_module_submodule_defn(this.getSourceVariable(), this.getDefiningNode()) } - } /** An implicit (possible) definition of an escaping variable at a call-site */ class CallsiteRefinement extends EssaNodeRefinement { - - override string toString() { - result = "CallsiteRefinement" - } + override string toString() { result = "CallsiteRefinement" } CallsiteRefinement() { exists(SsaSourceVariable var, ControlFlowNode defn | @@ -818,49 +689,37 @@ class CallsiteRefinement extends EssaNodeRefinement { ) } - CallNode getCall() { - this.getDefiningNode() = result - } - + CallNode getCall() { this.getDefiningNode() = result } } /** An implicit (possible) modification of the object referred at a method call */ class MethodCallsiteRefinement extends EssaNodeRefinement { - MethodCallsiteRefinement() { - SsaSource::method_call_refinement(this.getSourceVariable(), _, this.getDefiningNode()) - and not this instanceof SingleSuccessorGuard - } - - CallNode getCall() { - this.getDefiningNode() = result + SsaSource::method_call_refinement(this.getSourceVariable(), _, this.getDefiningNode()) and + not this instanceof SingleSuccessorGuard } + CallNode getCall() { this.getDefiningNode() = result } } /** An implicit (possible) modification of `self` at a method call */ class SelfCallsiteRefinement extends MethodCallsiteRefinement { - - SelfCallsiteRefinement() { - this.getSourceVariable().(Variable).isSelf() - } - + SelfCallsiteRefinement() { this.getSourceVariable().(Variable).isSelf() } } /** Python specific sub-class of generic EssaEdgeRefinement */ class PyEdgeRefinement extends EssaEdgeRefinement { - override string getRepresentation() { - /* This is for testing so use capital 'P' to make it sort before 'phi' and - * be more visually distinctive. */ + /* + * This is for testing so use capital 'P' to make it sort before 'phi' and + * be more visually distinctive. + */ + result = "Pi(" + this.getInput().getRepresentation() + ") [" + this.getSense() + "]" or not exists(this.getInput()) and result = "Pi(" + this.getSourceVariable().getName() + "??) [" + this.getSense() + "]" } - ControlFlowNode getTest() { - result = this.getPredecessor().getLastNode() - } - + ControlFlowNode getTest() { result = this.getPredecessor().getLastNode() } } diff --git a/python/ql/src/semmle/python/essa/SsaCompute.qll b/python/ql/src/semmle/python/essa/SsaCompute.qll index cd359a0edf3..5a0980ed973 100644 --- a/python/ql/src/semmle/python/essa/SsaCompute.qll +++ b/python/ql/src/semmle/python/essa/SsaCompute.qll @@ -1,28 +1,29 @@ -/** Provides predicates for computing Enhanced SSA form +/** + * Provides predicates for computing Enhanced SSA form * Computation of ESSA form is identical to plain SSA form, * but what counts as a use of definition differs. - * + * * ## Language independent data-flow graph construction - * + * * Construction of the data-flow graph is based on the principles behind SSA variables. - * + * * The definition of an SSA variable is that (statically): - * + * * * Each variable has exactly one definition * * A variable's definition dominates all its uses. - * - * SSA form was originally designed for compiler use and thus a "definition" of an SSA variable is - * the same as a definition of the underlying source-code variable. For register allocation this is + * + * SSA form was originally designed for compiler use and thus a "definition" of an SSA variable is + * the same as a definition of the underlying source-code variable. For register allocation this is * sufficient to treat the variable as equivalent to the value held in the variable. - * + * * However, this doesn't always work the way we want it for data-flow analysis. - * - * When we start to consider attribute assignment, tests on the value referred to be a variable, + * + * When we start to consider attribute assignment, tests on the value referred to be a variable, * escaping variables, implicit definitions, etc., we need something finer grained. - * + * * A data-flow variable has the same properties as a normal SSA variable, but it also has the property that * *anything* that may change the way we view an object referred to by a variable should be treated as a definition of that variable. - * + * * For example, tests are treated as definitions, so for the following Python code: * ```python * x = None @@ -39,7 +40,7 @@ * from which is it possible to infer that `x3` may not be None. * [ Phi functions are standard SSA, a Pi function is a filter or guard on the possible values that a variable * may hold] - * + * * Attribute assignments are also treated as definitions, so for the following Python code: * ```python * x = C() @@ -55,13 +56,13 @@ * y1 = attr-assign(y0, .b = 1) * ``` * From which we can infer that `x1.a` is `1` but we know nothing about `y0.a` despite it being the same type. - * + * * We can also insert "definitions" for transfers of values (say in global variables) where we do not yet know the call-graph. For example, * ```python * def foo(): * global g * g = 1 - * + * * def bar(): * foo() * g @@ -72,7 +73,7 @@ * def foo(): * g0 = scope-entry(g) * g1 = 1 - * + * * def bar(): * g2 = scope-entry(g) * foo() @@ -86,57 +87,63 @@ * g3 = g1 * ``` * and thus it falls out that `g3` must be `1`. - * */ - import python - -private cached module SsaComputeImpl { - - cached module EssaDefinitionsImpl { - +cached +private module SsaComputeImpl { + cached + module EssaDefinitionsImpl { /** Whether `n` is a live update that is a definition of the variable `v`. */ - cached predicate variableDefinition(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { + cached + predicate variableDefinition( + SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i + ) { SsaComputeImpl::variableDefine(v, n, b, i) and SsaComputeImpl::defUseRank(v, b, rankix, i) and - ( - SsaComputeImpl::defUseRank(v, b, rankix+1, _) and not SsaComputeImpl::defRank(v, b, rankix+1, _) + ( + SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and + not SsaComputeImpl::defRank(v, b, rankix + 1, _) or - not SsaComputeImpl::defUseRank(v, b, rankix+1, _) and Liveness::liveAtExit(v, b) + not SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and Liveness::liveAtExit(v, b) ) } /** Whether `n` is a live update that is a definition of the variable `v`. */ - cached predicate variableRefinement(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { + cached + predicate variableRefinement( + SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i + ) { SsaComputeImpl::variableRefine(v, n, b, i) and SsaComputeImpl::defUseRank(v, b, rankix, i) and - ( - SsaComputeImpl::defUseRank(v, b, rankix+1, _) and not SsaComputeImpl::defRank(v, b, rankix+1, _) + ( + SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and + not SsaComputeImpl::defRank(v, b, rankix + 1, _) or - not SsaComputeImpl::defUseRank(v, b, rankix+1, _) and Liveness::liveAtExit(v, b) + not SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and Liveness::liveAtExit(v, b) ) } - cached predicate variableUpdate(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { + cached + predicate variableUpdate(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { variableDefinition(v, n, b, rankix, i) or variableRefinement(v, n, b, rankix, i) } /** Holds if `def` is a pi-node for `v` on the edge `pred` -> `succ` */ - cached predicate piNode(SsaSourceVariable v, BasicBlock pred, BasicBlock succ) { + cached + predicate piNode(SsaSourceVariable v, BasicBlock pred, BasicBlock succ) { v.hasRefinementEdge(_, pred, succ) and Liveness::liveAtEntry(v, succ) } - /** A phi node for `v` at the beginning of basic block `b`. */ - cached predicate phiNode(SsaSourceVariable v, BasicBlock b) { + /** A phi node for `v` at the beginning of basic block `b`. */ + cached + predicate phiNode(SsaSourceVariable v, BasicBlock b) { ( - exists(BasicBlock def | def.dominanceFrontier(b) | - SsaComputeImpl::ssaDef(v, def) - ) + exists(BasicBlock def | def.dominanceFrontier(b) | SsaComputeImpl::ssaDef(v, def)) or piNode(v, _, b) and strictcount(b.getAPredecessor()) > 1 ) and @@ -144,25 +151,26 @@ private cached module SsaComputeImpl { } } - cached predicate variableDefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { - v.hasDefiningNode(n) - and + cached + predicate variableDefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { + v.hasDefiningNode(n) and exists(int j | n = b.getNode(j) and - i = j*2 + 1 + i = j * 2 + 1 ) } - cached predicate variableRefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { - v.hasRefinement(_, n) - and + cached + predicate variableRefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { + v.hasRefinement(_, n) and exists(int j | n = b.getNode(j) and - i = j*2 + 1 + i = j * 2 + 1 ) } - cached predicate variableDef(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { + cached + predicate variableDef(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { variableDefine(v, n, b, i) or variableRefine(v, n, b, i) } @@ -174,22 +182,25 @@ private cached module SsaComputeImpl { * irrelevant indices at which there is no definition or use when traversing * basic blocks. */ - cached predicate defUseRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { - i = rank[rankix](int j | variableDef(v, _, b, j) or variableUse(v, _, b, j)) + cached + predicate defUseRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { + i = rank[rankix](int j | variableDef(v, _, b, j) or variableUse(v, _, b, j)) } /** A definition of a variable occurring at the specified rank index in basic block `b`. */ - cached predicate defRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { - variableDef(v, _, b, i) and - defUseRank(v, b, rankix, i) + cached + predicate defRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { + variableDef(v, _, b, i) and + defUseRank(v, b, rankix, i) } /** A `VarAccess` `use` of `v` in `b` at index `i`. */ - cached predicate variableUse(SsaSourceVariable v, ControlFlowNode use, BasicBlock b, int i) { + cached + predicate variableUse(SsaSourceVariable v, ControlFlowNode use, BasicBlock b, int i) { (v.getAUse() = use or v.hasRefinement(use, _)) and exists(int j | - b.getNode(j) = use and - i = 2*j + b.getNode(j) = use and + i = 2 * j ) } @@ -197,7 +208,8 @@ private cached module SsaComputeImpl { * A definition of an SSA variable occurring at the specified position. * This is either a phi node, a `VariableUpdate`, or a parameter. */ - cached predicate ssaDef(SsaSourceVariable v, BasicBlock b) { + cached + predicate ssaDef(SsaSourceVariable v, BasicBlock b) { EssaDefinitions::phiNode(v, b) or EssaDefinitions::variableUpdate(v, _, b, _, _) @@ -216,10 +228,13 @@ private cached module SsaComputeImpl { */ /** The maximum rank index for the given variable and basic block. */ - cached int lastRank(SsaSourceVariable v, BasicBlock b) { + cached + int lastRank(SsaSourceVariable v, BasicBlock b) { result = max(int rankix | defUseRank(v, b, rankix, _)) or - not defUseRank(v, b, _, _) and (EssaDefinitions::phiNode(v, b) or EssaDefinitions::piNode(v, _, b)) and result = 0 + not defUseRank(v, b, _, _) and + (EssaDefinitions::phiNode(v, b) or EssaDefinitions::piNode(v, _, b)) and + result = 0 } private predicate ssaDefRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { @@ -227,22 +242,35 @@ private cached module SsaComputeImpl { or EssaDefinitions::phiNode(v, b) and rankix = 0 and i = phiIndex() or - EssaDefinitions::piNode(v, _, b) and EssaDefinitions::phiNode(v, b) and rankix = -1 and i = piIndex() + EssaDefinitions::piNode(v, _, b) and + EssaDefinitions::phiNode(v, b) and + rankix = -1 and + i = piIndex() or - EssaDefinitions::piNode(v, _, b) and not EssaDefinitions::phiNode(v, b) and rankix = 0 and i = piIndex() + EssaDefinitions::piNode(v, _, b) and + not EssaDefinitions::phiNode(v, b) and + rankix = 0 and + i = piIndex() } /** The SSA definition reaches the rank index `rankix` in its own basic block `b`. */ - cached predicate ssaDefReachesRank(SsaSourceVariable v, BasicBlock b, int i, int rankix) { - ssaDefRank(v, b, rankix, i) or - ssaDefReachesRank(v, b, i, rankix-1) and rankix <= lastRank(v, b) and not ssaDefRank(v, b, rankix, _) + cached + predicate ssaDefReachesRank(SsaSourceVariable v, BasicBlock b, int i, int rankix) { + ssaDefRank(v, b, rankix, i) + or + ssaDefReachesRank(v, b, i, rankix - 1) and + rankix <= lastRank(v, b) and + not ssaDefRank(v, b, rankix, _) } /** * The SSA definition of `v` at `def` reaches `use` in the same basic block * without crossing another SSA definition of `v`. */ - cached predicate ssaDefReachesUseWithinBlock(SsaSourceVariable v, BasicBlock b, int i, ControlFlowNode use) { + cached + predicate ssaDefReachesUseWithinBlock( + SsaSourceVariable v, BasicBlock b, int i, ControlFlowNode use + ) { exists(int rankix, int useix | ssaDefReachesRank(v, b, i, rankix) and defUseRank(v, b, rankix, useix) and @@ -250,41 +278,44 @@ private cached module SsaComputeImpl { ) } - cached module LivenessImpl { + cached + module LivenessImpl { + cached + predicate liveAtExit(SsaSourceVariable v, BasicBlock b) { liveAtEntry(v, b.getASuccessor()) } - cached predicate liveAtExit(SsaSourceVariable v, BasicBlock b) { - liveAtEntry(v, b.getASuccessor()) - } - - cached predicate liveAtEntry(SsaSourceVariable v, BasicBlock b) { + cached + predicate liveAtEntry(SsaSourceVariable v, BasicBlock b) { SsaComputeImpl::defUseRank(v, b, 1, _) and not SsaComputeImpl::defRank(v, b, 1, _) or not SsaComputeImpl::defUseRank(v, b, _, _) and liveAtExit(v, b) } - } - cached module SsaDefinitionsImpl { - - pragma [noinline] - private predicate reachesEndOfBlockRec(SsaSourceVariable v, BasicBlock defbb, int defindex, BasicBlock b) { + cached + module SsaDefinitionsImpl { + pragma[noinline] + private predicate reachesEndOfBlockRec( + SsaSourceVariable v, BasicBlock defbb, int defindex, BasicBlock b + ) { exists(BasicBlock idom | reachesEndOfBlock(v, defbb, defindex, idom) | idom = b.getImmediateDominator() ) } + /** * The SSA definition of `v` at `def` reaches the end of a basic block `b`, at * which point it is still live, without crossing another SSA definition of `v`. */ cached predicate reachesEndOfBlock(SsaSourceVariable v, BasicBlock defbb, int defindex, BasicBlock b) { - Liveness::liveAtExit(v, b) and - ( - defbb = b and SsaComputeImpl::ssaDefReachesRank(v, defbb, defindex, SsaComputeImpl::lastRank(v, b)) - or - // It is sufficient to traverse the dominator graph, cf. discussion above. - reachesEndOfBlockRec(v, defbb, defindex, b) and - not SsaComputeImpl::ssaDef(v, b) + Liveness::liveAtExit(v, b) and + ( + defbb = b and + SsaComputeImpl::ssaDefReachesRank(v, defbb, defindex, SsaComputeImpl::lastRank(v, b)) + or + // It is sufficient to traverse the dominator graph, cf. discussion above. + reachesEndOfBlockRec(v, defbb, defindex, b) and + not SsaComputeImpl::ssaDef(v, b) ) } @@ -294,15 +325,16 @@ private cached module SsaComputeImpl { */ cached predicate reachesUse(SsaSourceVariable v, BasicBlock defbb, int defindex, ControlFlowNode use) { - SsaComputeImpl::ssaDefReachesUseWithinBlock(v, defbb, defindex, use) or - exists(BasicBlock b | - SsaComputeImpl::variableUse(v, use, b, _) and - reachesEndOfBlock(v, defbb, defindex, b.getAPredecessor()) and - not SsaComputeImpl::ssaDefReachesUseWithinBlock(v, b, _, use) - ) + SsaComputeImpl::ssaDefReachesUseWithinBlock(v, defbb, defindex, use) + or + exists(BasicBlock b | + SsaComputeImpl::variableUse(v, use, b, _) and + reachesEndOfBlock(v, defbb, defindex, b.getAPredecessor()) and + not SsaComputeImpl::ssaDefReachesUseWithinBlock(v, b, _, use) + ) } - /*** + /** * Holds if `(defbb, defindex)` is an SSA definition of `v` that reaches an exit without crossing another * SSA definition of `v`. */ @@ -315,9 +347,7 @@ private cached module SsaComputeImpl { SsaComputeImpl::variableUse(v, use, last, index) ) } - } - } import SsaComputeImpl::SsaDefinitionsImpl as SsaDefinitions @@ -325,9 +355,8 @@ import SsaComputeImpl::EssaDefinitionsImpl as EssaDefinitions import SsaComputeImpl::LivenessImpl as Liveness /* This is exported primarily for testing */ - - -/* A note on numbering +/* + * A note on numbering * In order to create an SSA graph, we need an order of definitions and uses within a basic block. * To do this we index definitions and uses as follows: * Phi-functions have an index of -1, so precede all normal uses and definitions in a block. @@ -337,10 +366,8 @@ import SsaComputeImpl::LivenessImpl as Liveness * * a definition at the `j`th node of a block is given the index `2*j + 1`. */ -pragma [inline] +pragma[inline] int phiIndex() { result = -1 } -pragma [inline] +pragma[inline] int piIndex() { result = -2 } - - diff --git a/python/ql/src/semmle/python/essa/SsaDefinitions.qll b/python/ql/src/semmle/python/essa/SsaDefinitions.qll index 8a6bc274aa0..992a2bd96ac 100644 --- a/python/ql/src/semmle/python/essa/SsaDefinitions.qll +++ b/python/ql/src/semmle/python/essa/SsaDefinitions.qll @@ -1,44 +1,48 @@ -/** Provides classes and predicates for determining the uses and definitions of +/** + * Provides classes and predicates for determining the uses and definitions of * variables for ESSA form. */ import python private import semmle.python.pointsto.Base - - - -cached module SsaSource { - +cached +module SsaSource { /** Holds if `v` is used as the receiver in a method call. */ - cached predicate method_call_refinement(Variable v, ControlFlowNode use, CallNode call) { + cached + predicate method_call_refinement(Variable v, ControlFlowNode use, CallNode call) { use = v.getAUse() and call.getFunction().(AttrNode).getObject() = use and not test_contains(_, call) } /** Holds if `v` is defined by assignment at `defn` and given `value`. */ - cached predicate assignment_definition(Variable v, ControlFlowNode defn, ControlFlowNode value) { + cached + predicate assignment_definition(Variable v, ControlFlowNode defn, ControlFlowNode value) { defn.(NameNode).defines(v) and defn.(DefinitionNode).getValue() = value } /** Holds if `v` is defined by assignment of the captured exception. */ - cached predicate exception_capture(Variable v, NameNode defn) { + cached + predicate exception_capture(Variable v, NameNode defn) { defn.defines(v) and exists(ExceptFlowNode ex | ex.getName() = defn) } /** Holds if `v` is defined by a with statement. */ - cached predicate with_definition(Variable v, ControlFlowNode defn) { + cached + predicate with_definition(Variable v, ControlFlowNode defn) { exists(With with, Name var | with.getOptionalVars() = var and - var.getAFlowNode() = defn | + var.getAFlowNode() = defn + | var = v.getAStore() ) } /** Holds if `v` is defined by multiple assignment at `defn`. */ - cached predicate multi_assignment_definition(Variable v, ControlFlowNode defn, int n, SequenceNode lhs) { + cached + predicate multi_assignment_definition(Variable v, ControlFlowNode defn, int n, SequenceNode lhs) { ( defn.(NameNode).defines(v) or @@ -50,44 +54,52 @@ cached module SsaSource { } /** Holds if `v` is defined by a `for` statement, the definition being `defn` */ - cached predicate iteration_defined_variable(Variable v, ControlFlowNode defn, ControlFlowNode sequence) { + cached + predicate iteration_defined_variable(Variable v, ControlFlowNode defn, ControlFlowNode sequence) { exists(ForNode for | for.iterates(defn, sequence)) and defn.(NameNode).defines(v) } /** Holds if `v` is a parameter variable and `defn` is the CFG node for that parameter. */ - cached predicate parameter_definition(Variable v, ControlFlowNode defn) { + cached + predicate parameter_definition(Variable v, ControlFlowNode defn) { exists(Function f, Name param | f.getAnArg() = param or f.getVararg() = param or f.getKwarg() = param or - f.getKeywordOnlyArg(_) = param | + f.getKeywordOnlyArg(_) = param + | defn.getNode() = param and param.getVariable() = v ) } /** Holds if `v` is deleted at `del`. */ - cached predicate deletion_definition(Variable v, DeletionNode del) { + cached + predicate deletion_definition(Variable v, DeletionNode del) { del.getTarget().(NameNode).deletes(v) } - /** Holds if the name of `var` refers to a submodule of a package and `f` is the entry point + /** + * Holds if the name of `var` refers to a submodule of a package and `f` is the entry point * to the __init__ module of that package. */ - cached predicate init_module_submodule_defn(SsaSourceVariable var, ControlFlowNode f) { + cached + predicate init_module_submodule_defn(SsaSourceVariable var, ControlFlowNode f) { var instanceof GlobalVariable and exists(Module init | - init.isPackageInit() and exists(init.getPackage().getSubModule(var.getName())) and + init.isPackageInit() and + exists(init.getPackage().getSubModule(var.getName())) and init.getEntryNode() = f and var.getScope() = init ) } /** Holds if the `v` is in scope at a `from import ... *` and may thus be redefined by that statement */ - cached predicate import_star_refinement(SsaSourceVariable v, ControlFlowNode use, ControlFlowNode def) { - use = def and def instanceof ImportStarNode - and + cached + predicate import_star_refinement(SsaSourceVariable v, ControlFlowNode use, ControlFlowNode def) { + use = def and + def instanceof ImportStarNode and ( v.getScope() = def.getScope() or @@ -99,13 +111,16 @@ cached module SsaSource { } /** Holds if an attribute is assigned at `def` and `use` is the use of `v` for that assignment */ - cached predicate attribute_assignment_refinement(Variable v, ControlFlowNode use, ControlFlowNode def) { + cached + predicate attribute_assignment_refinement(Variable v, ControlFlowNode use, ControlFlowNode def) { use.(NameNode).uses(v) and - def.isStore() and def.(AttrNode).getObject() = use + def.isStore() and + def.(AttrNode).getObject() = use } /** Holds if a `v` is used as an argument to `call`, which *may* modify the object referred to by `v` */ - cached predicate argument_refinement(Variable v, ControlFlowNode use, CallNode call) { + cached + predicate argument_refinement(Variable v, ControlFlowNode use, CallNode call) { use.(NameNode).uses(v) and call.getArg(0) = use and not method_call_refinement(v, _, call) and @@ -113,13 +128,15 @@ cached module SsaSource { } /** Holds if an attribute is deleted at `def` and `use` is the use of `v` for that deletion */ - cached predicate attribute_deletion_refinement(Variable v, NameNode use, DeletionNode def) { + cached + predicate attribute_deletion_refinement(Variable v, NameNode use, DeletionNode def) { use.uses(v) and def.getTarget().(AttrNode).getObject() = use } /** Holds if the set of possible values for `v` is refined by `test` and `use` is the use of `v` in that test. */ - cached predicate test_refinement(Variable v, ControlFlowNode use, ControlFlowNode test) { + cached + predicate test_refinement(Variable v, ControlFlowNode use, ControlFlowNode test) { use.(NameNode).uses(v) and test.getAChild*() = use and test.isBranch() and @@ -129,5 +146,4 @@ cached module SsaSource { not block.getLastNode() = test ) } - } diff --git a/python/ql/src/semmle/python/filters/GeneratedCode.qll b/python/ql/src/semmle/python/filters/GeneratedCode.qll index 18696239d63..411cb558e7e 100644 --- a/python/ql/src/semmle/python/filters/GeneratedCode.qll +++ b/python/ql/src/semmle/python/filters/GeneratedCode.qll @@ -5,105 +5,118 @@ import semmle.python.templates.Templates * A file that is detected as being generated. */ abstract class GeneratedFile extends File { - abstract string getTool(); - } -/* We distinguish between a "lax" match which just includes "generated by" or similar versus a "strict" match which includes "this file is generated by" or similar +/* + * We distinguish between a "lax" match which just includes "generated by" or similar versus a "strict" match which includes "this file is generated by" or similar * "lax" matches are taken to indicate generated file if they occur at the top of a file. "strict" matches can occur anywhere. * There is no formal reason for the above, it just seems to work well in practice. */ library class GenericGeneratedFile extends GeneratedFile { - GenericGeneratedFile() { - not this instanceof SpecificGeneratedFile - and + not this instanceof SpecificGeneratedFile and ( - (lax_generated_by(this, _) or lax_generated_from(this, _)) and dont_modify(this) + (lax_generated_by(this, _) or lax_generated_from(this, _)) and + dont_modify(this) or - strict_generated_by(this, _) or strict_generated_from(this, _) + strict_generated_by(this, _) + or + strict_generated_from(this, _) or auto_generated(this) ) } - override string getTool() { - lax_generated_by(this, result) or strict_generated_by(this, result) - } - + override string getTool() { lax_generated_by(this, result) or strict_generated_by(this, result) } } private string comment_or_docstring(File f, boolean before_code) { - exists(Comment c | + exists(Comment c | c.getLocation().getFile() = f and - result = c.getText() | - if exists(Stmt s | s.getEnclosingModule().getFile() = f and s.getLocation().getStartLine() < c.getLocation().getStartLine()) then - before_code = false - else - before_code = true + result = c.getText() + | + if + exists(Stmt s | + s.getEnclosingModule().getFile() = f and + s.getLocation().getStartLine() < c.getLocation().getStartLine() + ) + then before_code = false + else before_code = true ) or exists(Module m | m.getFile() = f | result = m.getDocString().getText() and before_code = true ) - } private predicate lax_generated_by(File f, string tool) { exists(string comment | comment = comment_or_docstring(f, _) | - tool = comment.regexpCapture("(?is).*\\b(?:(?:auto[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", 1) + tool = + comment + .regexpCapture("(?is).*\\b(?:(?:auto[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", + 1) ) } private predicate lax_generated_from(File f, string src) { - exists(string comment | comment = comment_or_docstring(f, _) | - src = comment.regexpCapture("(?is).*\\b((?:auto[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", 1) - ) + exists(string comment | comment = comment_or_docstring(f, _) | + src = + comment + .regexpCapture("(?is).*\\b((?:auto[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", + 1) + ) } private predicate strict_generated_by(File f, string tool) { exists(string comment | comment = comment_or_docstring(f, true) | - tool = comment.regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", 1) + tool = + comment + .regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", + 1) ) } private predicate strict_generated_from(File f, string src) { exists(string comment | comment = comment_or_docstring(f, true) | - src = comment.regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", 1) + src = + comment + .regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", + 1) ) } private predicate dont_modify(File f) { - comment_or_docstring(f, _).regexpMatch("(?is).*\\b(Do not|Don't) (edit|modify|make changes)\\b.*") + comment_or_docstring(f, _).regexpMatch("(?is).*\\b(Do not|Don't) (edit|modify|make changes)\\b.*") } private predicate auto_generated(File f) { exists(Comment c | c.getLocation().getFile() = f and - c.getText().regexpMatch("(?is)# *this +(code|file) +is +(auto(matically)?[ -]?generated|created automatically).*") + c + .getText() + .regexpMatch("(?is)# *this +(code|file) +is +(auto(matically)?[ -]?generated|created automatically).*") ) } - /** - * A file generated by a template engine + * A file generated by a template engine */ abstract library class SpecificGeneratedFile extends GeneratedFile { - /* Currently cover Spitfire, Pyxl and Mako. + /* + * Currently cover Spitfire, Pyxl and Mako. * Django templates are not compiled to Python. * Jinja2 templates are compiled direct to bytecode via the ast. */ -} + + } /** File generated by the spitfire templating engine */ class SpitfireGeneratedFile extends SpecificGeneratedFile { - SpitfireGeneratedFile() { - exists(Module m | - m.getFile() = this and not m instanceof SpitfireTemplate | + exists(Module m | m.getFile() = this and not m instanceof SpitfireTemplate | exists(ImportMember template_method, ImportExpr spitfire_runtime_template | spitfire_runtime_template.getName() = "spitfire.runtime.template" and template_method.getModule() = spitfire_runtime_template and @@ -112,28 +125,18 @@ class SpitfireGeneratedFile extends SpecificGeneratedFile { ) } - override string getTool() { - result = "spitfire" - } - + override string getTool() { result = "spitfire" } } /** File generated by the pyxl templating engine */ class PyxlGeneratedFile extends SpecificGeneratedFile { + PyxlGeneratedFile() { this.getSpecifiedEncoding() = "pyxl" } - PyxlGeneratedFile() { - this.getSpecifiedEncoding() = "pyxl" - } - - override string getTool() { - result = "pyxl" - } - + override string getTool() { result = "pyxl" } } /** File generated by the mako templating engine */ class MakoGeneratedFile extends SpecificGeneratedFile { - MakoGeneratedFile() { exists(Module m | m.getFile() = this | from_mako_import(m) = "runtime" and @@ -147,38 +150,31 @@ class MakoGeneratedFile extends SpecificGeneratedFile { ) and exists(Assign a, Name n | a.getScope() = m and a.getATarget() = n and n.getId() = "_magic_number" - ) + ) ) } - override string getTool() { - result = "mako" - } - + override string getTool() { result = "mako" } } string from_mako_import(Module m) { exists(ImportMember member, ImportExpr mako | member.getScope() = m and member.getModule() = mako and - mako.getName() = "mako" | - result = member.getName() + mako.getName() = "mako" + | + result = member.getName() ) } /** File generated by Google's protobuf tool. */ class ProtobufGeneratedFile extends SpecificGeneratedFile { - ProtobufGeneratedFile() { - this.getName().regexpMatch(".*_pb2?.py") - and - exists(Module m | - m.getFile() = this | - exists(ImportExpr imp | - imp.getEnclosingModule() = m | + this.getName().regexpMatch(".*_pb2?.py") and + exists(Module m | m.getFile() = this | + exists(ImportExpr imp | imp.getEnclosingModule() = m | imp.getImportedModuleName() = "google.net.proto2.python.public" - ) - and + ) and exists(AssignStmt a, Name n | a.getEnclosingModule() = m and a.getATarget() = n and @@ -187,8 +183,5 @@ class ProtobufGeneratedFile extends SpecificGeneratedFile { ) } - override string getTool() { - result = "protobuf" - } - + override string getTool() { result = "protobuf" } } diff --git a/python/ql/src/semmle/python/filters/Tests.qll b/python/ql/src/semmle/python/filters/Tests.qll index 6c42fec61ab..7b9c2fa38cd 100644 --- a/python/ql/src/semmle/python/filters/Tests.qll +++ b/python/ql/src/semmle/python/filters/Tests.qll @@ -1,12 +1,11 @@ import python -abstract class TestScope extends Scope {} +abstract class TestScope extends Scope { } // don't extend Class directly to avoid ambiguous method warnings class UnitTestClass extends TestScope { UnitTestClass() { - exists(ClassObject c | - this = c.getPyClass() | + exists(ClassObject c | this = c.getPyClass() | c.getASuperType() = theUnitTestPackage().attr(_) or c.getASuperType().getName().toLowerCase() = "testcase" @@ -14,35 +13,27 @@ class UnitTestClass extends TestScope { } } -PackageObject theUnitTestPackage() { - result.getName() = "unittest" -} +PackageObject theUnitTestPackage() { result.getName() = "unittest" } -abstract class Test extends TestScope {} +abstract class Test extends TestScope { } class UnitTestFunction extends Test { - UnitTestFunction() { - this.getScope+() instanceof UnitTestClass - and + this.getScope+() instanceof UnitTestClass and this.(Function).getName().matches("test%") } } class PyTestFunction extends Test { - PyTestFunction() { exists(Module pytest | pytest.getName() = "pytest") and this.(Function).getName().matches("test%") } - } class NoseTestFunction extends Test { - NoseTestFunction() { exists(Module nose | nose.getName() = "nose") and this.(Function).getName().matches("test%") } - } diff --git a/python/ql/src/semmle/python/libraries/Zope.qll b/python/ql/src/semmle/python/libraries/Zope.qll index 8f69c792b5d..381e40edeab 100644 --- a/python/ql/src/semmle/python/libraries/Zope.qll +++ b/python/ql/src/semmle/python/libraries/Zope.qll @@ -1,12 +1,10 @@ /** Utilities for handling the zope libraries */ import python - private import semmle.python.pointsto.PointsTo /** A method that to a sub-class of `zope.interface.Interface` */ deprecated class ZopeInterfaceMethod extends PyFunctionObject { - /** Holds if this method belongs to a class that sub-classes `zope.interface.Interface` */ ZopeInterfaceMethod() { exists(Object interface, ClassObject owner | @@ -16,22 +14,17 @@ deprecated class ZopeInterfaceMethod extends PyFunctionObject { ) } - override int minParameters() { - result = super.minParameters() + 1 - } + override int minParameters() { result = super.minParameters() + 1 } override int maxParameters() { - if exists(this.getFunction().getVararg()) then - result = super.maxParameters() - else - result = super.maxParameters() + 1 + if exists(this.getFunction().getVararg()) + then result = super.maxParameters() + else result = super.maxParameters() + 1 } - } /** A method that belongs to a sub-class of `zope.interface.Interface` */ class ZopeInterfaceMethodValue extends PythonFunctionValue { - /** Holds if this method belongs to a class that sub-classes `zope.interface.Interface` */ ZopeInterfaceMethodValue() { exists(Value interface, ClassValue owner | @@ -44,15 +37,11 @@ class ZopeInterfaceMethodValue extends PythonFunctionValue { ) } - override int minParameters() { - result = super.minParameters() + 1 - } + override int minParameters() { result = super.minParameters() + 1 } override int maxParameters() { - if exists(this.getScope().getVararg()) then - result = super.maxParameters() - else - result = super.maxParameters() + 1 + if exists(this.getScope().getVararg()) + then result = super.maxParameters() + else result = super.maxParameters() + 1 } - } diff --git a/python/ql/src/semmle/python/protocols.qll b/python/ql/src/semmle/python/protocols.qll index 31808ff3c53..f1f7e6a3ed7 100644 --- a/python/ql/src/semmle/python/protocols.qll +++ b/python/ql/src/semmle/python/protocols.qll @@ -1,31 +1,19 @@ import python /** Retained for backwards compatibility use ClassObject.isIterator() instead. */ -predicate is_iterator(ClassObject c) { - c.isIterator() -} +predicate is_iterator(ClassObject c) { c.isIterator() } /** Retained for backwards compatibility use ClassObject.isIterable() instead. */ -predicate is_iterable(ClassObject c) { - c.isIterable() -} +predicate is_iterable(ClassObject c) { c.isIterable() } /** Retained for backwards compatibility use ClassObject.isCollection() instead. */ -predicate is_collection(ClassObject c) { - c.isCollection() -} +predicate is_collection(ClassObject c) { c.isCollection() } /** Retained for backwards compatibility use ClassObject.isMapping() instead. */ -predicate is_mapping(ClassObject c) { - c.isMapping() -} +predicate is_mapping(ClassObject c) { c.isMapping() } /** Retained for backwards compatibility use ClassObject.isSequence() instead. */ -predicate is_sequence(ClassObject c) { - c.isSequence() -} +predicate is_sequence(ClassObject c) { c.isSequence() } /** Retained for backwards compatibility use ClassObject.isContextManager() instead. */ -predicate is_context_manager(ClassObject c) { - c.isContextManager() -} +predicate is_context_manager(ClassObject c) { c.isContextManager() } diff --git a/python/ql/src/semmle/python/regex.qll b/python/ql/src/semmle/python/regex.qll index 2e83d8fca35..bd7469ea830 100644 --- a/python/ql/src/semmle/python/regex.qll +++ b/python/ql/src/semmle/python/regex.qll @@ -2,13 +2,20 @@ import python import semmle.python.objects.ObjectInternal private predicate re_module_function(string name, int flags) { - name = "compile" and flags = 1 or - name = "search" and flags = 2 or - name = "match" and flags = 2 or - name = "split" and flags = 3 or - name = "findall" and flags = 2 or - name = "finditer" and flags = 2 or - name = "sub" and flags = 4 or + name = "compile" and flags = 1 + or + name = "search" and flags = 2 + or + name = "match" and flags = 2 + or + name = "split" and flags = 3 + or + name = "findall" and flags = 2 + or + name = "finditer" and flags = 2 + or + name = "sub" and flags = 4 + or name = "subn" and flags = 4 } @@ -17,16 +24,15 @@ private predicate re_module_function(string name, int flags) { * If regex mode is not known, `mode` will be `"None"`. */ predicate used_as_regex(Expr s, string mode) { - (s instanceof Bytes or s instanceof Unicode) - and + (s instanceof Bytes or s instanceof Unicode) and /* Call to re.xxx(regex, ... [mode]) */ exists(CallNode call, string name | call.getArg(0).refersTo(_, _, s.getAFlowNode()) and - call.getFunction().pointsTo(Module::named("re").attr(name)) | + call.getFunction().pointsTo(Module::named("re").attr(name)) + | mode = "None" or - exists(Value obj | - mode = mode_from_mode_object(obj) | + exists(Value obj | mode = mode_from_mode_object(obj) | exists(int flags_arg | re_module_function(name, flags_arg) and call.getArg(flags_arg).pointsTo(obj) @@ -39,30 +45,30 @@ predicate used_as_regex(Expr s, string mode) { string mode_from_mode_object(Value obj) { ( - result = "DEBUG" or result = "IGNORECASE" or result = "LOCALE" or - result = "MULTILINE" or result = "DOTALL" or result = "UNICODE" or + result = "DEBUG" or + result = "IGNORECASE" or + result = "LOCALE" or + result = "MULTILINE" or + result = "DOTALL" or + result = "UNICODE" or result = "VERBOSE" ) and exists(int flag | - flag = Value::named("sre_constants.SRE_FLAG_" + result).(ObjectInternal).intValue() - and + flag = Value::named("sre_constants.SRE_FLAG_" + result).(ObjectInternal).intValue() and obj.(ObjectInternal).intValue().bitAnd(flag) = flag ) } /** A StrConst used as a regular expression */ abstract class RegexString extends Expr { - - RegexString() { - (this instanceof Bytes or this instanceof Unicode) - } + RegexString() { (this instanceof Bytes or this instanceof Unicode) } predicate char_set_start(int start, int end) { this.nonEscapedCharAt(start) = "[" and ( - this.getChar(start+1) = "^" and end = start + 2 - or - not this.getChar(start+1) = "^" and end = start + 1 + this.getChar(start + 1) = "^" and end = start + 2 + or + not this.getChar(start + 1) = "^" and end = start + 1 ) } @@ -70,58 +76,47 @@ abstract class RegexString extends Expr { predicate charSet(int start, int end) { exists(int inner_start, int inner_end | this.char_set_start(start, inner_start) and - not this.char_set_start(_, start) | - end = inner_end + 1 and inner_end > inner_start and + not this.char_set_start(_, start) + | + end = inner_end + 1 and + inner_end > inner_start and this.nonEscapedCharAt(inner_end) = "]" and - not exists(int mid | this.nonEscapedCharAt(mid) = "]" | - mid > inner_start and mid < inner_end - ) + not exists(int mid | this.nonEscapedCharAt(mid) = "]" | mid > inner_start and mid < inner_end) ) } - predicate escapingChar(int pos) { - this.escaping(pos) = true - } + predicate escapingChar(int pos) { this.escaping(pos) = true } private boolean escaping(int pos) { pos = -1 and result = false or - this.getChar(pos) = "\\" and result = this.escaping(pos-1).booleanNot() + this.getChar(pos) = "\\" and result = this.escaping(pos - 1).booleanNot() or this.getChar(pos) != "\\" and result = false } /** Gets the text of this regex */ string getText() { - result = ((Unicode)this).getS() + result = this.(Unicode).getS() or - result = ((Bytes)this).getS() + result = this.(Bytes).getS() } - string getChar(int i) { - result = this.getText().charAt(i) - } + string getChar(int i) { result = this.getText().charAt(i) } string nonEscapedCharAt(int i) { result = this.getText().charAt(i) and - not this.escapingChar(i-1) + not this.escapingChar(i - 1) } - private predicate isOptionDivider(int i) { - this.nonEscapedCharAt(i) = "|" - } + private predicate isOptionDivider(int i) { this.nonEscapedCharAt(i) = "|" } - private predicate isGroupEnd(int i) { - this.nonEscapedCharAt(i) = ")" - } + private predicate isGroupEnd(int i) { this.nonEscapedCharAt(i) = ")" } - private predicate isGroupStart(int i) { - this.nonEscapedCharAt(i) = "(" - } + private predicate isGroupStart(int i) { this.nonEscapedCharAt(i) = "(" } predicate failedToParse(int i) { - exists(this.getChar(i)) - and + exists(this.getChar(i)) and not exists(int start, int end | this.top_level(start, end) and start <= i and @@ -130,42 +125,47 @@ abstract class RegexString extends Expr { } private predicate escapedCharacter(int start, int end) { - this.escapingChar(start) and not exists(this.getText().substring(start+1, end+1).toInt()) and + this.escapingChar(start) and + not exists(this.getText().substring(start + 1, end + 1).toInt()) and ( - this.getChar(start+1) = "x" and end = start + 4 + this.getChar(start + 1) = "x" and end = start + 4 or - end in [start+2..start+4] and - exists(this.getText().substring(start+1, end).toInt()) + end in [start + 2 .. start + 4] and + exists(this.getText().substring(start + 1, end).toInt()) or - this.getChar(start+1) != "x" and end = start + 2 + this.getChar(start + 1) != "x" and end = start + 2 ) } private predicate inCharSet(int index) { - exists(int x, int y | this.charSet(x, y) and index in [x+1 .. y-2]) + exists(int x, int y | this.charSet(x, y) and index in [x + 1 .. y - 2]) } - /* 'simple' characters are any that don't alter the parsing of the regex. + /* + * 'simple' characters are any that don't alter the parsing of the regex. */ + private predicate simpleCharacter(int start, int end) { - end = start+1 and + end = start + 1 and not this.charSet(start, _) and - not this.charSet(_, start+1) and - exists(string c | - c = this.getChar(start) | + not this.charSet(_, start + 1) and + exists(string c | c = this.getChar(start) | exists(int x, int y, int z | - this.charSet(x, z) and - this.char_set_start(x, y) | + this.charSet(x, z) and + this.char_set_start(x, y) + | start = y or - start = z-2 + start = z - 2 or - start > y and start < z-2 and not c = "-" + start > y and start < z - 2 and not c = "-" ) or not this.inCharSet(start) and - not c = "(" and not c = "[" and - not c = ")" and not c = "|" and + not c = "(" and + not c = "[" and + not c = ")" and + not c = "|" and not this.qualifier(start, _, _) ) } @@ -176,28 +176,20 @@ abstract class RegexString extends Expr { not exists(int x, int y | this.escapedCharacter(x, y) and x <= start and y >= end) or this.escapedCharacter(start, end) - ) - and - not exists(int x, int y | - this.group_start(x, y) and x <= start and y >= end - ) + ) and + not exists(int x, int y | this.group_start(x, y) and x <= start and y >= end) } predicate normalCharacter(int start, int end) { - this.character(start, end) - and + this.character(start, end) and not this.specialCharacter(start, end, _) } predicate specialCharacter(int start, int end, string char) { - this.character(start, end) - and - end = start+1 - and - char = this.getChar(start) - and - (char = "$" or char = "^" or char = ".") - and + this.character(start, end) and + end = start + 1 and + char = this.getChar(start) and + (char = "$" or char = "^" or char = ".") and not this.inCharSet(start) } @@ -210,17 +202,17 @@ abstract class RegexString extends Expr { /** Gets the number of the group in start,end */ int getGroupNumber(int start, int end) { - this.group(start, end) and - result = count(int i | this.group(i, _) and i < start and not this.non_capturing_group_start(i, _)) + 1 + this.group(start, end) and + result = + count(int i | this.group(i, _) and i < start and not this.non_capturing_group_start(i, _)) + 1 } /** Gets the name, if it has one, of the group in start,end */ string getGroupName(int start, int end) { - this.group(start, end) - and + this.group(start, end) and exists(int name_end | this.named_group_start(start, name_end) and - result = this.getText().substring(start+4, name_end-1) + result = this.getText().substring(start + 4, name_end - 1) ) } @@ -236,8 +228,7 @@ abstract class RegexString extends Expr { } private predicate emptyGroup(int start, int end) { - exists(int endm1 | - end = endm1+1 | + exists(int endm1 | end = endm1 + 1 | this.group_start(start, endm1) and this.isGroupEnd(endm1) ) @@ -263,21 +254,20 @@ abstract class RegexString extends Expr { exists(int in_start | this.negative_lookahead_assertion_start(start, in_start) or - this.negative_lookbehind_assertion_start(start, in_start) | + this.negative_lookbehind_assertion_start(start, in_start) + | this.groupContents(start, end, in_start, _) ) } private predicate positiveLookaheadAssertionGroup(int start, int end) { - exists(int in_start | - this.lookahead_assertion_start(start, in_start) | + exists(int in_start | this.lookahead_assertion_start(start, in_start) | this.groupContents(start, end, in_start, _) ) } private predicate positiveLookbehindAssertionGroup(int start, int end) { - exists(int in_start | - this.lookbehind_assertion_start(start, in_start) | + exists(int in_start | this.lookbehind_assertion_start(start, in_start) | this.groupContents(start, end, in_start, _) ) } @@ -306,42 +296,43 @@ abstract class RegexString extends Expr { private predicate non_capturing_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = ":" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = ":" and + end = start + 3 } private predicate simple_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) != "?" and end = start+1 + this.getChar(start + 1) != "?" and + end = start + 1 } private predicate named_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "P" and - this.getChar(start+3) = "<" and - not this.getChar(start+4) = "=" and - not this.getChar(start+4) = "!" and + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "P" and + this.getChar(start + 3) = "<" and + not this.getChar(start + 4) = "=" and + not this.getChar(start + 4) = "!" and exists(int name_end | - name_end = min(int i | i > start+4 and this.getChar(i) = ">") and + name_end = min(int i | i > start + 4 and this.getChar(i) = ">") and end = name_end + 1 ) } private predicate named_backreference_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "P" and - this.getChar(start+3) = "=" and - end = min(int i | i > start+4 and this.getChar(i) = "?") + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "P" and + this.getChar(start + 3) = "=" and + end = min(int i | i > start + 4 and this.getChar(i) = "?") } private predicate flag_group_start(int start, int end, string c) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - end = start+3 and - c = this.getChar(start+2) and + this.getChar(start + 1) = "?" and + end = start + 3 and + c = this.getChar(start + 2) and ( c = "i" or c = "L" or @@ -352,12 +343,12 @@ abstract class RegexString extends Expr { ) } - /** Gets the mode of this regular expression string if + /** + * Gets the mode of this regular expression string if * it is defined by a prefix. */ string getModeFromPrefix() { - exists(string c | - this.flag_group_start(_, _, c) | + exists(string c | this.flag_group_start(_, _, c) | c = "i" and result = "IGNORECASE" or c = "L" and result = "LOCALE" @@ -366,7 +357,7 @@ abstract class RegexString extends Expr { or c = "s" and result = "DOTALL" or - c = "u" and result = "UNICODE" + c = "u" and result = "UNICODE" or c = "x" and result = "VERBOSE" ) @@ -374,39 +365,39 @@ abstract class RegexString extends Expr { private predicate lookahead_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "=" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "=" and + end = start + 3 } private predicate negative_lookahead_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "!" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "!" and + end = start + 3 } private predicate lookbehind_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "<" and - this.getChar(start+3) = "=" and - end = start+4 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "<" and + this.getChar(start + 3) = "=" and + end = start + 4 } private predicate negative_lookbehind_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "<" and - this.getChar(start+3) = "!" and - end = start+4 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "<" and + this.getChar(start + 3) = "!" and + end = start + 4 } private predicate comment_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "#" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "#" and + end = start + 3 } predicate groupContents(int start, int end, int in_start, int in_end) { @@ -417,20 +408,21 @@ abstract class RegexString extends Expr { } private predicate named_backreference(int start, int end, string name) { - this.named_backreference_start(start, start+4) and - end = min(int i | i > start+4 and this.getChar(i) = ")") + 1 and - name = this.getText().substring(start+4, end-2) + this.named_backreference_start(start, start + 4) and + end = min(int i | i > start + 4 and this.getChar(i) = ")") + 1 and + name = this.getText().substring(start + 4, end - 2) } private predicate numbered_backreference(int start, int end, int value) { - this.escapingChar(start) - and + this.escapingChar(start) and exists(string text, string svalue, int len | end = start + len and - text = this.getText() and len in [2..3] | - svalue = text.substring(start+1, start+len) and + text = this.getText() and + len in [2 .. 3] + | + svalue = text.substring(start + 1, start + len) and value = svalue.toInt() and - not exists(text.substring(start+1, start+len+1).toInt()) and + not exists(text.substring(start + 1, start + len + 1).toInt()) and value != 0 ) } @@ -443,17 +435,14 @@ abstract class RegexString extends Expr { } /** Gets the number of the back reference in start,end */ - int getBackrefNumber(int start, int end) { - this.numbered_backreference(start, end, result) - } + int getBackrefNumber(int start, int end) { this.numbered_backreference(start, end, result) } /** Gets the name, if it has one, of the back reference in start,end */ - string getBackrefName(int start, int end) { - this.named_backreference(start, end, result) - } + string getBackrefName(int start, int end) { this.named_backreference(start, end, result) } private predicate baseItem(int start, int end) { - this.character(start, end) and not exists(int x, int y | this.charSet(x, y) and x <= start and y >= end) + this.character(start, end) and + not exists(int x, int y | this.charSet(x, y) and x <= start and y >= end) or this.group(start, end) or @@ -463,12 +452,8 @@ abstract class RegexString extends Expr { private predicate qualifier(int start, int end, boolean maybe_empty) { this.short_qualifier(start, end, maybe_empty) and not this.getChar(end) = "?" or - exists(int short_end | - this.short_qualifier(start, short_end, maybe_empty) | - if this.getChar(short_end) = "?" then - end = short_end+1 - else - end = short_end + exists(int short_end | this.short_qualifier(start, short_end, maybe_empty) | + if this.getChar(short_end) = "?" then end = short_end + 1 else end = short_end ) } @@ -479,26 +464,28 @@ abstract class RegexString extends Expr { this.getChar(start) = "*" and maybe_empty = true or this.getChar(start) = "?" and maybe_empty = true - ) and end = start + 1 + ) and + end = start + 1 or exists(int endin | end = endin + 1 | - this.getChar(start) = "{" and this.getChar(endin) = "}" and + this.getChar(start) = "{" and + this.getChar(endin) = "}" and end > start and - exists(string multiples | - multiples = this.getText().substring(start+1, endin) | + exists(string multiples | multiples = this.getText().substring(start + 1, endin) | multiples.regexpMatch("0*,[0-9]*") and maybe_empty = true or multiples.regexpMatch("0*[1-9][0-9]*,[0-9]*") and maybe_empty = false - ) - and + ) and not exists(int mid | this.getChar(mid) = "}" and - mid > start and mid < endin + mid > start and + mid < endin ) ) } - /** Whether the text in the range start,end is a qualified item, where item is a character, + /** + * Whether the text in the range start,end is a qualified item, where item is a character, * a character set or a group. */ predicate qualifiedItem(int start, int end, boolean maybe_empty) { @@ -520,19 +507,18 @@ abstract class RegexString extends Expr { ( start = 0 or this.group_start(_, start) or - this.isOptionDivider(start-1) - ) - and - this.item(start, end) or - ( - exists(int mid | - this.subsequence(start, mid) and - this.item(mid, end) - ) + this.isOptionDivider(start - 1) + ) and + this.item(start, end) + or + exists(int mid | + this.subsequence(start, mid) and + this.item(mid, end) ) } - /** Whether the text in the range start,end is a sequence of 1 or more items, where an item is a character, + /** + * Whether the text in the range start,end is a sequence of 1 or more items, where an item is a character, * a character set or a group. */ predicate sequence(int start, int end) { @@ -552,9 +538,12 @@ abstract class RegexString extends Expr { } private predicate item_end(int end) { - this.character(_, end) or - exists(int endm1 | this.isGroupEnd(endm1) and end = endm1 + 1) or - this.charSet(_, end) or + this.character(_, end) + or + exists(int endm1 | this.isGroupEnd(endm1) and end = endm1 + 1) + or + this.charSet(_, end) + or this.qualifier(_, end, _) } @@ -564,30 +553,36 @@ abstract class RegexString extends Expr { } private predicate subalternation(int start, int end, int item_start) { - this.sequenceOrQualified(start, end) and not this.isOptionDivider(start-1) and + this.sequenceOrQualified(start, end) and + not this.isOptionDivider(start - 1) and item_start = start or - start = end and not this.item_end(start) and this.isOptionDivider(end) and + start = end and + not this.item_end(start) and + this.isOptionDivider(end) and item_start = start or exists(int mid | this.subalternation(start, mid, _) and this.isOptionDivider(mid) and - item_start = mid+1 | + item_start = mid + 1 + | this.sequenceOrQualified(item_start, end) or not this.item_start(end) and end = item_start ) } - /** Whether the text in the range start,end is an alternation + /** + * Whether the text in the range start,end is an alternation */ predicate alternation(int start, int end) { this.top_level(start, end) and exists(int less | this.subalternation(start, less, _) and less < end) } - /** Whether the text in the range start,end is an alternation and the text in part_start, part_end is one of the + /** + * Whether the text in the range start,end is an alternation and the text in part_start, part_end is one of the * options in that alternation. */ predicate alternationOption(int start, int end, int part_start, int part_end) { @@ -599,22 +594,19 @@ abstract class RegexString extends Expr { private predicate firstPart(int start, int end) { start = 0 and end = this.getText().length() or - exists(int x | - this.firstPart(x, end) | + exists(int x | this.firstPart(x, end) | this.emptyMatchAtStartGroup(x, start) or this.qualifiedItem(x, start, true) or this.specialCharacter(x, start, "^") ) or - exists(int y | - this.firstPart(start, y) | + exists(int y | this.firstPart(start, y) | this.item(start, end) or this.qualifiedPart(start, end, y, _) ) or - exists(int x, int y | - this.firstPart(x, y) | + exists(int x, int y | this.firstPart(x, y) | this.groupContents(x, y, start, end) or this.alternationOption(x, y, start, end) @@ -625,8 +617,7 @@ abstract class RegexString extends Expr { private predicate lastPart(int start, int end) { start = 0 and end = this.getText().length() or - exists(int y | - this.lastPart(start, y) | + exists(int y | this.lastPart(start, y) | this.emptyMatchAtEndGroup(end, y) or this.qualifiedItem(end, y, true) or this.specialCharacter(end, y, "$") @@ -637,60 +628,52 @@ abstract class RegexString extends Expr { this.item(start, end) ) or - exists(int y | - this.lastPart(start, y) | - this.qualifiedPart(start, end, y, _) - ) + exists(int y | this.lastPart(start, y) | this.qualifiedPart(start, end, y, _)) or - exists(int x, int y | - this.lastPart(x, y) | + exists(int x, int y | this.lastPart(x, y) | this.groupContents(x, y, start, end) or this.alternationOption(x, y, start, end) ) } - /** Whether the item at [start, end) is one of the first items + /** + * Whether the item at [start, end) is one of the first items * to be matched. */ predicate firstItem(int start, int end) { ( - this.character(start, end) - or - this.qualifiedItem(start, end, _) - or - this.charSet(start, end) - ) - and + this.character(start, end) + or + this.qualifiedItem(start, end, _) + or + this.charSet(start, end) + ) and this.firstPart(start, end) } - /** Whether the item at [start, end) is one of the last items + /** + * Whether the item at [start, end) is one of the last items * to be matched. */ predicate lastItem(int start, int end) { ( - this.character(start, end) - or - this.qualifiedItem(start, end, _) - or - this.charSet(start, end) - ) - and + this.character(start, end) + or + this.qualifiedItem(start, end, _) + or + this.charSet(start, end) + ) and this.lastPart(start, end) } - } - /** A StrConst used as a regular expression */ class Regex extends RegexString { + Regex() { used_as_regex(this, _) } - Regex() { - used_as_regex(this, _) - } - - /** Gets a mode (if any) of this regular expression. Can be any of: + /** + * Gets a mode (if any) of this regular expression. Can be any of: * DEBUG * IGNORECASE * LOCALE @@ -705,5 +688,4 @@ class Regex extends RegexString { or result = this.getModeFromPrefix() } - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/strings.qll b/python/ql/src/semmle/python/strings.qll index f94921aa263..e366d191669 100644 --- a/python/ql/src/semmle/python/strings.qll +++ b/python/ql/src/semmle/python/strings.qll @@ -9,23 +9,22 @@ predicate mapping_format(StrConst e) { } /* -MAPPING_KEY = "(\\([^)]+\\))?" -CONVERSION_FLAGS = "[#0\\- +]?" -MINIMUM_FIELD_WIDTH = "(\\*|[0-9]*)" -PRECISION = "(\\.(\\*|[0-9]*))?" -LENGTH_MODIFIER = "[hlL]?" -TYPE = "[bdiouxXeEfFgGcrs%]" -*/ + * MAPPING_KEY = "(\\([^)]+\\))?" + * CONVERSION_FLAGS = "[#0\\- +]?" + * MINIMUM_FIELD_WIDTH = "(\\*|[0-9]*)" + * PRECISION = "(\\.(\\*|[0-9]*))?" + * LENGTH_MODIFIER = "[hlL]?" + * TYPE = "[bdiouxXeEfFgGcrs%]" + */ -private -string conversion_specifier_string(StrConst e, int number, int position) { +private string conversion_specifier_string(StrConst e, int number, int position) { exists(string s, string REGEX | s = e.getText() | REGEX = "%(\\([^)]*\\))?[#0\\- +]*(\\*|[0-9]*)(\\.(\\*|[0-9]*))?(h|H|l|L)?[badiouxXeEfFgGcrs%]" and - result = s.regexpFind(REGEX, number, position)) + result = s.regexpFind(REGEX, number, position) + ) } -private -string conversion_specifier(StrConst e, int number) { +private string conversion_specifier(StrConst e, int number) { result = conversion_specifier_string(e, number, _) and result != "%%" } @@ -39,22 +38,17 @@ int illegal_conversion_specifier(StrConst e) { /** Gets the number of format items in a format string */ int format_items(StrConst e) { - result = count(int i | | conversion_specifier(e, i)) + - // a conversion specifier uses an extra item for each * - count(int i, int j | conversion_specifier(e, i).charAt(j) = "*") + result = + count(int i | | conversion_specifier(e, i)) + + // a conversion specifier uses an extra item for each * + count(int i, int j | conversion_specifier(e, i).charAt(j) = "*") } private string str(Expr e) { - result = ((Num)e).getN() + result = e.(Num).getN() or - result = "'" + ((StrConst)e).getText() + "'" + result = "'" + e.(StrConst).getText() + "'" } /** Gets a string representation of an expression more suited for embedding in message strings than .toString() */ -string repr(Expr e) { - if exists(str(e)) then - result = str(e) - else - result = e.toString() -} - +string repr(Expr e) { if exists(str(e)) then result = str(e) else result = e.toString() } diff --git a/python/ql/src/semmle/python/templates/PyxlTags.qll b/python/ql/src/semmle/python/templates/PyxlTags.qll index 3ab3f8980bc..07f4aa44e03 100644 --- a/python/ql/src/semmle/python/templates/PyxlTags.qll +++ b/python/ql/src/semmle/python/templates/PyxlTags.qll @@ -1,32 +1,22 @@ - - import python -/** A Tag in Pyxl (which gets converted to a call in Python). - * +/** + * A Tag in Pyxl (which gets converted to a call in Python). */ class PyxlTag extends Call { + PyxlTag() { pyxl_tag(this, _) } - PyxlTag() { - pyxl_tag(this, _) - } - - string getPyxlTagName() { - pyxl_tag(this, result) - } + string getPyxlTagName() { pyxl_tag(this, result) } /** Gets the pyxl or Python node that is enclosed by this one in the pyxl source */ - Expr getEnclosedNode() { - none() - } + Expr getEnclosedNode() { none() } /** Gets the Python code (if any) that is contained in this pyxl node */ Expr getEnclosedPythonCode() { result = this.getEnclosedNode() and not result instanceof PyxlTag or - result = ((PyxlTag)this.getEnclosedNode()).getEnclosedPythonCode() + result = this.getEnclosedNode().(PyxlTag).getEnclosedPythonCode() } - } private predicate pyxl_tag(Call c, string name) { @@ -39,53 +29,33 @@ private predicate pyxl_tag(Call c, string name) { } class PyxlHtmlTag extends PyxlTag { + PyxlHtmlTag() { this.getPyxlTagName().prefix(2) = "x_" } - PyxlHtmlTag() { - this.getPyxlTagName().prefix(2) = "x_" - } - - string getTagName() { - result = this.getPyxlTagName().suffix(2) - } + string getTagName() { result = this.getPyxlTagName().suffix(2) } /** Html tags get transformed into a call. This node is the callee function and the enclosed node is an argument. */ override Expr getEnclosedNode() { - exists(Call c | + exists(Call c | c.getFunc() = this and result = c.getAnArg() ) } - } class PyxlIfTag extends PyxlTag { + PyxlIfTag() { this.getPyxlTagName() = "_push_condition" } - PyxlIfTag() { - this.getPyxlTagName() = "_push_condition" - } - - override Expr getEnclosedNode() { - result = this.getAnArg() - } + override Expr getEnclosedNode() { result = this.getAnArg() } } class PyxlEndIfTag extends PyxlTag { + PyxlEndIfTag() { this.getPyxlTagName() = "_leave_if" } - PyxlEndIfTag() { - this.getPyxlTagName() = "_leave_if" - } - - override Expr getEnclosedNode() { - result = this.getAnArg() - } - + override Expr getEnclosedNode() { result = this.getAnArg() } } -class PyxlRawHtml extends PyxlTag{ - - PyxlRawHtml() { - this.getPyxlTagName() = "rawhtml" - } +class PyxlRawHtml extends PyxlTag { + PyxlRawHtml() { this.getPyxlTagName() = "rawhtml" } /** The text for this raw html, if it is simple text. */ string getText() { @@ -95,13 +65,7 @@ class PyxlRawHtml extends PyxlTag{ ) } - Expr getValue() { - result = this.getArg(0) - } - - override Expr getEnclosedNode() { - result = this.getAnArg() - } + Expr getValue() { result = this.getArg(0) } + override Expr getEnclosedNode() { result = this.getAnArg() } } - diff --git a/python/ql/src/semmle/python/templates/Templates.qll b/python/ql/src/semmle/python/templates/Templates.qll index 2aec12119a2..00aacd232a0 100644 --- a/python/ql/src/semmle/python/templates/Templates.qll +++ b/python/ql/src/semmle/python/templates/Templates.qll @@ -1,24 +1,15 @@ import python - -abstract class Template extends Module { - -} +abstract class Template extends Module { } class SpitfireTemplate extends Template { - - SpitfireTemplate() { - this.getKind() = "Spitfire template" - } - + SpitfireTemplate() { this.getKind() = "Spitfire template" } } class PyxlModule extends Template { - - PyxlModule() { + PyxlModule() { exists(Comment c | c.getLocation().getFile() = this.getFile() | c.getText().regexpMatch("# *coding.*pyxl.*") ) - } - + } } diff --git a/python/ql/src/semmle/python/values/StringAttributes.qll b/python/ql/src/semmle/python/values/StringAttributes.qll index 248a11f6ae2..1209313eaf1 100644 --- a/python/ql/src/semmle/python/values/StringAttributes.qll +++ b/python/ql/src/semmle/python/values/StringAttributes.qll @@ -1,10 +1,12 @@ import python predicate string_attribute_all(ControlFlowNode n, string attr) { - (n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and attr = "const" + (n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and + attr = "const" or exists(Object s | - n.refersTo(s, theBytesType(), _) and attr = "bytes" and + n.refersTo(s, theBytesType(), _) and + attr = "bytes" and // We are only interested in bytes if they may cause an exception if // implicitly converted to unicode. ASCII is safe. not s.(StringObject).isAscii() @@ -12,23 +14,19 @@ predicate string_attribute_all(ControlFlowNode n, string attr) { } predicate tracked_object(ControlFlowNode obj, string attr) { - tracked_object_all(obj, attr) - or - tracked_object_any(obj, attr) + tracked_object_all(obj, attr) + or + tracked_object_any(obj, attr) } -predicate open_file(Object obj) { - obj.(CallNode).getFunction().refersTo(Object::builtin("open")) -} +predicate open_file(Object obj) { obj.(CallNode).getFunction().refersTo(Object::builtin("open")) } predicate string_attribute_any(ControlFlowNode n, string attr) { attr = "user-input" and - exists(Object input | - n.(CallNode).getFunction().refersTo(input) | - if major_version() = 2 then - input = Object::builtin("raw_input") - else - input = Object::builtin("input") + exists(Object input | n.(CallNode).getFunction().refersTo(input) | + if major_version() = 2 + then input = Object::builtin("raw_input") + else input = Object::builtin("input") ) or attr = "file-input" and @@ -42,19 +40,13 @@ predicate string_attribute_any(ControlFlowNode n, string attr) { predicate tracked_object_any(ControlFlowNode obj, string attr) { string_attribute_any(obj, attr) or - exists(ControlFlowNode other | - tracking_step(other, obj) | - tracked_object_any(other, attr) - ) + exists(ControlFlowNode other | tracking_step(other, obj) | tracked_object_any(other, attr)) } predicate tracked_object_all(ControlFlowNode obj, string attr) { string_attribute_all(obj, attr) or - forex(ControlFlowNode other | - tracking_step(other, obj) | - tracked_object_all(other, attr) - ) + forex(ControlFlowNode other | tracking_step(other, obj) | tracked_object_all(other, attr)) } predicate tracked_call_step(ControlFlowNode ret, ControlFlowNode call) { @@ -72,7 +64,7 @@ ControlFlowNode sequence_for_iterator(ControlFlowNode f) { ) } -pragma [noinline] +pragma[noinline] private predicate tracking_step(ControlFlowNode src, ControlFlowNode dest) { src = dest.(BinaryExprNode).getAnOperand() or @@ -86,5 +78,5 @@ private predicate tracking_step(ControlFlowNode src, ControlFlowNode dest) { or tracked_call_step(src, dest) or - dest.refersTo((Object)src) + dest.refersTo(src.(Object)) } From 6904898a8b5fa8a2b13350a9f42d69d0febd136f Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:42:46 +0100 Subject: [PATCH 116/459] Python: Autoformat query-local libs. --- python/ql/src/Classes/ClassAttributes.qll | 159 +++++++-------- python/ql/src/Classes/Equality.qll | 31 +-- python/ql/src/Classes/MethodCallOrder.qll | 27 +-- python/ql/src/Exceptions/NotImplemented.qll | 1 - python/ql/src/Exceptions/Raising.qll | 10 +- python/ql/src/Expressions/CallArgs.qll | 179 ++++++++--------- .../Formatting/AdvancedFormatting.qll | 92 ++++----- python/ql/src/Expressions/IsComparisons.qll | 79 ++++---- .../src/Expressions/RedundantComparison.qll | 18 +- python/ql/src/Lexical/CommentedOutCode.qll | 188 +++++++++--------- python/ql/src/Metrics/Internal/Extents.qll | 18 +- python/ql/src/Testing/Mox.qll | 7 +- .../src/analysis/CrossProjectDefinitions.qll | 55 +++-- python/ql/src/analysis/DefinitionTracking.qll | 176 ++++++++-------- 14 files changed, 504 insertions(+), 536 deletions(-) diff --git a/python/ql/src/Classes/ClassAttributes.qll b/python/ql/src/Classes/ClassAttributes.qll index 262ff1058e8..5da7d29ace3 100644 --- a/python/ql/src/Classes/ClassAttributes.qll +++ b/python/ql/src/Classes/ClassAttributes.qll @@ -3,7 +3,6 @@ private import semmle.python.pointsto.PointsTo /** Helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */ class CheckClass extends ClassObject { - private predicate ofInterest() { not this.unknowableAttributes() and not this.getPyClass().isProbableMixin() and @@ -19,7 +18,8 @@ class CheckClass extends ClassObject { forall(ClassObject sup | sup = this.getAnImproperSuperType() and sup.declaresAttribute("__init__") and - not sup = theObjectType() | + not sup = theObjectType() + | sup.declaredAttribute("__init__") instanceof PyFunctionObject ) } @@ -32,108 +32,111 @@ class CheckClass extends ClassObject { } predicate sometimesDefines(string name) { - this.alwaysDefines(name) or - exists(SelfAttributeStore sa | - sa.getScope().getScope+() = this.getAnImproperSuperType().getPyClass() | + this.alwaysDefines(name) + or + exists(SelfAttributeStore sa | + sa.getScope().getScope+() = this.getAnImproperSuperType().getPyClass() + | name = sa.getName() ) } private predicate selfDictAssigns() { - exists(Assign a, SelfAttributeRead self_dict, Subscript sub | + exists(Assign a, SelfAttributeRead self_dict, Subscript sub | self_dict.getName() = "__dict__" and - ( - self_dict = sub.getObject() - or - /* Indirect assignment via temporary variable */ - exists(SsaVariable v | - v.getAUse() = sub.getObject().getAFlowNode() and - v.getDefinition().(DefinitionNode).getValue() = self_dict.getAFlowNode() - ) + ( + self_dict = sub.getObject() + or + /* Indirect assignment via temporary variable */ + exists(SsaVariable v | + v.getAUse() = sub.getObject().getAFlowNode() and + v.getDefinition().(DefinitionNode).getValue() = self_dict.getAFlowNode() + ) ) and a.getATarget() = sub and - exists(FunctionObject meth | meth = this.lookupAttribute(_) and a.getScope() = meth.getFunction()) + exists(FunctionObject meth | + meth = this.lookupAttribute(_) and a.getScope() = meth.getFunction() + ) ) } - pragma [nomagic] + pragma[nomagic] private predicate monkeyPatched(string name) { exists(Attribute a | - a.getCtx() instanceof Store and - PointsTo::points_to(a.getObject().getAFlowNode(), _, this, _, _) and a.getName() = name + a.getCtx() instanceof Store and + PointsTo::points_to(a.getObject().getAFlowNode(), _, this, _, _) and + a.getName() = name ) } private predicate selfSetattr() { - exists(Call c, Name setattr, Name self, Function method | - ( method.getScope() = this.getPyClass() or - method.getScope() = this.getASuperType().getPyClass() - ) and - c.getScope() = method and - c.getFunc() = setattr and - setattr.getId() = "setattr" and - c.getArg(0) = self and - self.getId() = "self" - ) + exists(Call c, Name setattr, Name self, Function method | + ( + method.getScope() = this.getPyClass() or + method.getScope() = this.getASuperType().getPyClass() + ) and + c.getScope() = method and + c.getFunc() = setattr and + setattr.getId() = "setattr" and + c.getArg(0) = self and + self.getId() = "self" + ) } - predicate interestingUndefined(SelfAttributeRead a) { - exists(string name | name = a.getName() | - interestingContext(a, name) and - not this.definedInBlock(a.getAFlowNode().getBasicBlock(), name) - ) - } + predicate interestingUndefined(SelfAttributeRead a) { + exists(string name | name = a.getName() | + interestingContext(a, name) and + not this.definedInBlock(a.getAFlowNode().getBasicBlock(), name) + ) + } - private predicate interestingContext(SelfAttributeRead a, string name) { - name = a.getName() and - this.ofInterest() and - this.getPyClass() = a.getScope().getScope() and - not a.locallyDefined() and - not a.guardedByHasattr() and - a.getScope().isPublic() and - not this.monkeyPatched(name) and - not attribute_assigned_in_method(lookupAttribute("setUp"), name) - } + private predicate interestingContext(SelfAttributeRead a, string name) { + name = a.getName() and + this.ofInterest() and + this.getPyClass() = a.getScope().getScope() and + not a.locallyDefined() and + not a.guardedByHasattr() and + a.getScope().isPublic() and + not this.monkeyPatched(name) and + not attribute_assigned_in_method(lookupAttribute("setUp"), name) + } - private predicate probablyAbstract() { - this.getName().matches("Abstract%") - or - this.isAbstract() - } + private predicate probablyAbstract() { + this.getName().matches("Abstract%") + or + this.isAbstract() + } - private pragma[nomagic] predicate definitionInBlock(BasicBlock b, string name) { - exists(SelfAttributeStore sa | - sa.getAFlowNode().getBasicBlock() = b and sa.getName() = name and sa.getClass() = this.getPyClass() - ) - or - exists(FunctionObject method | this.lookupAttribute(_) = method | - attribute_assigned_in_method(method, name) and - b = method.getACall().getBasicBlock() - ) - } - - private pragma[nomagic] predicate definedInBlock(BasicBlock b, string name) { - // manual specialisation: this is only called from interestingUndefined, - // so we can push the context in from there, which must apply to a - // SelfAttributeRead in the same scope - exists(SelfAttributeRead a | - a.getScope() = b.getScope() and name = a.getName() | - interestingContext(a, name) - ) - and - this.definitionInBlock(b, name) - or - exists(BasicBlock prev | this.definedInBlock(prev, name) and prev.getASuccessor() = b) - } + pragma[nomagic] + private predicate definitionInBlock(BasicBlock b, string name) { + exists(SelfAttributeStore sa | + sa.getAFlowNode().getBasicBlock() = b and + sa.getName() = name and + sa.getClass() = this.getPyClass() + ) + or + exists(FunctionObject method | this.lookupAttribute(_) = method | + attribute_assigned_in_method(method, name) and + b = method.getACall().getBasicBlock() + ) + } + pragma[nomagic] + private predicate definedInBlock(BasicBlock b, string name) { + // manual specialisation: this is only called from interestingUndefined, + // so we can push the context in from there, which must apply to a + // SelfAttributeRead in the same scope + exists(SelfAttributeRead a | a.getScope() = b.getScope() and name = a.getName() | + interestingContext(a, name) + ) and + this.definitionInBlock(b, name) + or + exists(BasicBlock prev | this.definedInBlock(prev, name) and prev.getASuccessor() = b) + } } - private Object object_getattribute() { result.asBuiltin() = theObjectType().asBuiltin().getMember("__getattribute__") } -private predicate auto_name(string name) { - name = "__class__" or name = "__dict__" -} - +private predicate auto_name(string name) { name = "__class__" or name = "__dict__" } diff --git a/python/ql/src/Classes/Equality.qll b/python/ql/src/Classes/Equality.qll index 7f546c42ecd..27d17d863a4 100644 --- a/python/ql/src/Classes/Equality.qll +++ b/python/ql/src/Classes/Equality.qll @@ -1,6 +1,5 @@ import python - private Attribute dictAccess(LocalVariable var) { result.getName() = "__dict__" and result.getObject() = var.getAnAccess() @@ -12,18 +11,21 @@ private Call getattr(LocalVariable obj, LocalVariable attr) { result.getArg(1) = attr.getAnAccess() } -/** A generic equality method that compares all attributes in its dict, - * or compares attributes using `getattr`. */ +/** + * A generic equality method that compares all attributes in its dict, + * or compares attributes using `getattr`. + */ class GenericEqMethod extends Function { - GenericEqMethod() { this.getName() = "__eq__" and exists(LocalVariable self, LocalVariable other | - self.getAnAccess() = this.getArg(0) and self.getId() = "self" and + self.getAnAccess() = this.getArg(0) and + self.getId() = "self" and other.getAnAccess() = this.getArg(1) and - exists(Compare eq | + exists(Compare eq | eq.getOp(0) instanceof Eq or - eq.getOp(0) instanceof NotEq | + eq.getOp(0) instanceof NotEq + | // `self.__dict__ == other.__dict__` eq.getAChildNode() = dictAccess(self) and eq.getAChildNode() = dictAccess(other) @@ -40,11 +42,11 @@ class GenericEqMethod extends Function { /** An `__eq__` method that just does `self is other` */ class IdentityEqMethod extends Function { - IdentityEqMethod() { this.getName() = "__eq__" and exists(LocalVariable self, LocalVariable other | - self.getAnAccess() = this.getArg(0) and self.getId() = "self" and + self.getAnAccess() = this.getArg(0) and + self.getId() = "self" and other.getAnAccess() = this.getArg(1) and exists(Compare eq | eq.getOp(0) instanceof Is | eq.getAChildNode() = self.getAnAccess() and @@ -52,19 +54,20 @@ class IdentityEqMethod extends Function { ) ) } - } /** An (in)equality method that delegates to its complement */ class DelegatingEqualityMethod extends Function { - DelegatingEqualityMethod() { exists(Return ret, UnaryExpr not_, Compare comp, Cmpop op, Parameter p0, Parameter p1 | ret.getScope() = this and ret.getValue() = not_ and - not_.getOp() instanceof Not and not_.getOperand() = comp and - comp.compares(p0.getVariable().getAnAccess(), op, p1.getVariable().getAnAccess()) | - this.getName() = "__eq__" and op instanceof NotEq or + not_.getOp() instanceof Not and + not_.getOperand() = comp and + comp.compares(p0.getVariable().getAnAccess(), op, p1.getVariable().getAnAccess()) + | + this.getName() = "__eq__" and op instanceof NotEq + or this.getName() = "__ne__" and op instanceof Eq ) } diff --git a/python/ql/src/Classes/MethodCallOrder.qll b/python/ql/src/Classes/MethodCallOrder.qll index 2960d652052..494c234da3c 100644 --- a/python/ql/src/Classes/MethodCallOrder.qll +++ b/python/ql/src/Classes/MethodCallOrder.qll @@ -1,17 +1,20 @@ import python // Helper predicates for multiple call to __init__/__del__ queries. - -pragma [noinline] -private predicate multiple_invocation_paths_helper(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { +pragma[noinline] +private predicate multiple_invocation_paths_helper( + FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi +) { i1 != i2 and i1 = top.getACallee+() and i2 = top.getACallee+() and i1.getFunction() = multi } -pragma [noinline] -private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { +pragma[noinline] +private predicate multiple_invocation_paths( + FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi +) { multiple_invocation_paths_helper(top, i1, i2, multi) and i2.getFunction() = multi } @@ -21,7 +24,8 @@ predicate multiple_calls_to_superclass_method(ClassObject self, FunctionObject m exists(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2 | multiple_invocation_paths(top, i1, i2, multi) and top.runtime(self.declaredAttribute(name)) and - self.getASuperType().declaredAttribute(name) = multi | + self.getASuperType().declaredAttribute(name) = multi + | // Only called twice if called from different functions, // or if one call-site can reach the other. i1.getCall().getScope() != i2.getCall().getScope() @@ -53,7 +57,9 @@ private predicate missing_call(FunctionObject meth, string name) { } /** Holds if `self.name` does not call `missing`, even though it is expected to. */ -predicate missing_call_to_superclass_method(ClassObject self, FunctionObject top, FunctionObject missing, string name) { +predicate missing_call_to_superclass_method( + ClassObject self, FunctionObject top, FunctionObject missing, string name +) { missing = self.getASuperType().declaredAttribute(name) and top = self.lookupAttribute(name) and /* There is no call to missing originating from top */ @@ -63,10 +69,7 @@ predicate missing_call_to_superclass_method(ClassObject self, FunctionObject top sup = self.getAnImproperSuperType() and named_attributes_not_method(sup, name) ) and - not self.isAbstract() - and - does_something(missing) - and + not self.isAbstract() and + does_something(missing) and not missing_call(top, name) } - diff --git a/python/ql/src/Exceptions/NotImplemented.qll b/python/ql/src/Exceptions/NotImplemented.qll index 09b3c37998b..b319311290e 100644 --- a/python/ql/src/Exceptions/NotImplemented.qll +++ b/python/ql/src/Exceptions/NotImplemented.qll @@ -1,4 +1,3 @@ - import python /** Holds if `notimpl` refers to `NotImplemented` or `NotImplemented()` in the `raise` statement */ diff --git a/python/ql/src/Exceptions/Raising.qll b/python/ql/src/Exceptions/Raising.qll index 7e53c0bbd27..ad98c93d0c4 100644 --- a/python/ql/src/Exceptions/Raising.qll +++ b/python/ql/src/Exceptions/Raising.qll @@ -1,16 +1,12 @@ import python -/** Whether the raise statement 'r' raises 'type' from origin 'orig' */ +/** Whether the raise statement 'r' raises 'type' from origin 'orig' */ predicate type_or_typeof(Raise r, ClassValue type, AstNode orig) { - exists(Expr exception | - exception = r.getRaised() | + exists(Expr exception | exception = r.getRaised() | exception.pointsTo(type, orig) or not exists(ClassValue exc_type | exception.pointsTo(exc_type)) and not type = ClassValue::type() and // First value is an unknown exception type - exists(Value val | exception.pointsTo(val, orig) | - val.getClass() = type - ) + exists(Value val | exception.pointsTo(val, orig) | val.getClass() = type) ) - } diff --git a/python/ql/src/Expressions/CallArgs.qll b/python/ql/src/Expressions/CallArgs.qll index e362256fd36..6d9baf6223d 100644 --- a/python/ql/src/Expressions/CallArgs.qll +++ b/python/ql/src/Expressions/CallArgs.qll @@ -1,14 +1,10 @@ import python - import Testing.Mox private int varargs_length_objectapi(Call call) { not exists(call.getStarargs()) and result = 0 or - exists(TupleObject t | - call.getStarargs().refersTo(t) | - result = t.getLength() - ) + exists(TupleObject t | call.getStarargs().refersTo(t) | result = t.getLength()) or result = count(call.getStarargs().(List).getAnElt()) } @@ -16,10 +12,7 @@ private int varargs_length_objectapi(Call call) { private int varargs_length(Call call) { not exists(call.getStarargs()) and result = 0 or - exists(TupleValue t | - call.getStarargs().pointsTo(t) | - result = t.length() - ) + exists(TupleValue t | call.getStarargs().pointsTo(t) | result = t.length()) or result = count(call.getStarargs().(List).getAnElt()) } @@ -38,43 +31,43 @@ private Keyword not_keyword_only_arg(Call call, FunctionValue func) { not func.getScope().getAKeywordOnlyArg().getId() = result.getArg() } -/** Gets the count of arguments that are passed as positional parameters even if they +/** + * Gets the count of arguments that are passed as positional parameters even if they * are named in the call. * This is the sum of the number of positional arguments, the number of elements in any explicit tuple passed as *arg * plus the number of keyword arguments that do not match keyword-only arguments (if the function does not take **kwargs). */ - private int positional_arg_count_for_call_objectapi(Call call, Object callable) { call = get_a_call_objectapi(callable).getNode() and exists(int positional_keywords | - exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) | - not func.getFunction().hasKwArg() and - positional_keywords = count(not_keyword_only_arg_objectapi(call, func)) - or - func.getFunction().hasKwArg() and positional_keywords = 0 - ) - | - result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords + exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) | + not func.getFunction().hasKwArg() and + positional_keywords = count(not_keyword_only_arg_objectapi(call, func)) + or + func.getFunction().hasKwArg() and positional_keywords = 0 + ) + | + result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords ) } -/** Gets the count of arguments that are passed as positional parameters even if they +/** + * Gets the count of arguments that are passed as positional parameters even if they * are named in the call. * This is the sum of the number of positional arguments, the number of elements in any explicit tuple passed as *arg * plus the number of keyword arguments that do not match keyword-only arguments (if the function does not take **kwargs). */ - private int positional_arg_count_for_call(Call call, Value callable) { call = get_a_call(callable).getNode() and exists(int positional_keywords | - exists(FunctionValue func | func = get_function_or_initializer(callable) | - not func.getScope().hasKwArg() and - positional_keywords = count(not_keyword_only_arg(call, func)) - or - func.getScope().hasKwArg() and positional_keywords = 0 - ) - | - result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords + exists(FunctionValue func | func = get_function_or_initializer(callable) | + not func.getScope().hasKwArg() and + positional_keywords = count(not_keyword_only_arg(call, func)) + or + func.getScope().hasKwArg() and positional_keywords = 0 + ) + | + result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords ) } @@ -88,33 +81,32 @@ int arg_count(Call call) { /* Gets a call corresponding to the given class or function*/ private ControlFlowNode get_a_call_objectapi(Object callable) { - result = callable.(ClassObject).getACall() - or - result = callable.(FunctionObject).getACall() + result = callable.(ClassObject).getACall() + or + result = callable.(FunctionObject).getACall() } /* Gets a call corresponding to the given class or function*/ private ControlFlowNode get_a_call(Value callable) { - result = callable.(ClassValue).getACall() - or - result = callable.(FunctionValue).getACall() + result = callable.(ClassValue).getACall() + or + result = callable.(FunctionValue).getACall() } /* Gets the function object corresponding to the given class or function*/ FunctionObject get_function_or_initializer_objectapi(Object func_or_cls) { - result = func_or_cls.(FunctionObject) - or - result = func_or_cls.(ClassObject).declaredAttribute("__init__") + result = func_or_cls.(FunctionObject) + or + result = func_or_cls.(ClassObject).declaredAttribute("__init__") } /* Gets the function object corresponding to the given class or function*/ FunctionValue get_function_or_initializer(Value func_or_cls) { - result = func_or_cls.(FunctionValue) - or - result = func_or_cls.(ClassValue).declaredAttribute("__init__") + result = func_or_cls.(FunctionValue) + or + result = func_or_cls.(ClassValue).declaredAttribute("__init__") } - /**Whether there is an illegally named parameter called `name` in the `call` to `func` */ predicate illegally_named_parameter_objectapi(Call call, Object func, string name) { not func.isC() and @@ -135,19 +127,22 @@ predicate illegally_named_parameter(Call call, Value func, string name) { predicate too_few_args_objectapi(Call call, Object callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter_objectapi(call, callable, _) and - not exists(call.getStarargs()) and not exists(call.getKwargs()) and + not exists(call.getStarargs()) and + not exists(call.getKwargs()) and arg_count_objectapi(call) < limit and exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) | - call = func.getAFunctionCall().getNode() and limit = func.minParameters() and - // The combination of misuse of `mox.Mox().StubOutWithMock()` - // and a bug in mox's implementation of methods results in having to - // pass 1 too few arguments to the mocked function. - not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) - or - call = func.getAMethodCall().getNode() and limit = func.minParameters() - 1 - or - callable instanceof ClassObject and - call.getAFlowNode() = get_a_call_objectapi(callable) and limit = func.minParameters() - 1 + call = func.getAFunctionCall().getNode() and + limit = func.minParameters() and + // The combination of misuse of `mox.Mox().StubOutWithMock()` + // and a bug in mox's implementation of methods results in having to + // pass 1 too few arguments to the mocked function. + not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) + or + call = func.getAMethodCall().getNode() and limit = func.minParameters() - 1 + or + callable instanceof ClassObject and + call.getAFlowNode() = get_a_call_objectapi(callable) and + limit = func.minParameters() - 1 ) } @@ -155,19 +150,22 @@ predicate too_few_args_objectapi(Call call, Object callable, int limit) { predicate too_few_args(Call call, Value callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter(call, callable, _) and - not exists(call.getStarargs()) and not exists(call.getKwargs()) and + not exists(call.getStarargs()) and + not exists(call.getKwargs()) and arg_count(call) < limit and exists(FunctionValue func | func = get_function_or_initializer(callable) | - call = func.getACall().getNode() and limit = func.minParameters() and - // The combination of misuse of `mox.Mox().StubOutWithMock()` - // and a bug in mox's implementation of methods results in having to - // pass 1 too few arguments to the mocked function. - not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) - or - call = func.getACall().getNode() and limit = func.minParameters() - 1 - or - callable instanceof ClassValue and - call.getAFlowNode() = get_a_call(callable) and limit = func.minParameters() - 1 + call = func.getACall().getNode() and + limit = func.minParameters() and + // The combination of misuse of `mox.Mox().StubOutWithMock()` + // and a bug in mox's implementation of methods results in having to + // pass 1 too few arguments to the mocked function. + not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) + or + call = func.getACall().getNode() and limit = func.minParameters() - 1 + or + callable instanceof ClassValue and + call.getAFlowNode() = get_a_call(callable) and + limit = func.minParameters() - 1 ) } @@ -175,16 +173,18 @@ predicate too_few_args(Call call, Value callable, int limit) { predicate too_many_args_objectapi(Call call, Object callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter_objectapi(call, callable, _) and - exists(FunctionObject func | - func = get_function_or_initializer_objectapi(callable) and - not func.getFunction().hasVarArg() and limit >= 0 - | + exists(FunctionObject func | + func = get_function_or_initializer_objectapi(callable) and + not func.getFunction().hasVarArg() and + limit >= 0 + | call = func.getAFunctionCall().getNode() and limit = func.maxParameters() - or + or call = func.getAMethodCall().getNode() and limit = func.maxParameters() - 1 - or + or callable instanceof ClassObject and - call.getAFlowNode() = get_a_call_objectapi(callable) and limit = func.maxParameters() - 1 + call.getAFlowNode() = get_a_call_objectapi(callable) and + limit = func.maxParameters() - 1 ) and positional_arg_count_for_call_objectapi(call, callable) > limit } @@ -193,16 +193,18 @@ predicate too_many_args_objectapi(Call call, Object callable, int limit) { predicate too_many_args(Call call, Value callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter(call, callable, _) and - exists(FunctionValue func | - func = get_function_or_initializer(callable) and - not func.getScope().hasVarArg() and limit >= 0 - | + exists(FunctionValue func | + func = get_function_or_initializer(callable) and + not func.getScope().hasVarArg() and + limit >= 0 + | call = func.getACall().getNode() and limit = func.maxParameters() - or + or call = func.getACall().getNode() and limit = func.maxParameters() - 1 - or + or callable instanceof ClassValue and - call.getAFlowNode() = get_a_call(callable) and limit = func.maxParameters() - 1 + call.getAFlowNode() = get_a_call(callable) and + limit = func.maxParameters() - 1 ) and positional_arg_count_for_call(call, callable) > limit } @@ -221,35 +223,34 @@ predicate wrong_args(Call call, FunctionValue func, int limit, string too) { too_many_args(call, func, limit) and too = "too many" } -/** Holds if `call` has correct number of arguments for `func`. +/** + * Holds if `call` has correct number of arguments for `func`. * Implies nothing about whether `call` could call `func`. */ - bindingset[call, func] +bindingset[call, func] predicate correct_args_if_called_as_method_objectapi(Call call, FunctionObject func) { - arg_count_objectapi(call)+1 >= func.minParameters() - and + arg_count_objectapi(call) + 1 >= func.minParameters() and arg_count_objectapi(call) < func.maxParameters() } -/** Holds if `call` has correct number of arguments for `func`. +/** + * Holds if `call` has correct number of arguments for `func`. * Implies nothing about whether `call` could call `func`. */ - bindingset[call, func] +bindingset[call, func] predicate correct_args_if_called_as_method(Call call, FunctionValue func) { - arg_count(call)+1 >= func.minParameters() - and + arg_count(call) + 1 >= func.minParameters() and arg_count(call) < func.maxParameters() } /** Holds if `call` is a call to `overriding`, which overrides `func`. */ -predicate overridden_call_objectapi(FunctionObject func, FunctionObject overriding, Call call) { +predicate overridden_call_objectapi(FunctionObject func, FunctionObject overriding, Call call) { overriding.overrides(func) and overriding.getACall().getNode() = call } /** Holds if `call` is a call to `overriding`, which overrides `func`. */ -predicate overridden_call(FunctionValue func, FunctionValue overriding, Call call) { +predicate overridden_call(FunctionValue func, FunctionValue overriding, Call call) { overriding.overrides(func) and overriding.getACall().getNode() = call } - diff --git a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll index f32b338c8ac..85b2fbad22a 100644 --- a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll +++ b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll @@ -1,11 +1,7 @@ import python - library class PossibleAdvancedFormatString extends StrConst { - - PossibleAdvancedFormatString() { - this.getText().matches("%{%}%") - } + PossibleAdvancedFormatString() { this.getText().matches("%{%}%") } private predicate field(int start, int end) { brace_pair(this, start, end) and @@ -31,83 +27,77 @@ library class PossibleAdvancedFormatString extends StrConst { ( result = this.getText().substring(start, end).regexpCapture("\\{([^!:.\\[]+)[!:.\\[].*", 1) or - result = this.getText().substring(start+1, end-1) and result.regexpMatch("[^!:.\\[]+") + result = this.getText().substring(start + 1, end - 1) and result.regexpMatch("[^!:.\\[]+") ) } /** Gets the name of the formatting field at [start, end) */ string getFieldName(int start, int end) { - result = this.fieldId(start, end) - and not exists(this.getFieldNumber(start, end)) + result = this.fieldId(start, end) and + not exists(this.getFieldNumber(start, end)) } private predicate implicitlyNumberedField(int start, int end) { this.field(start, end) and - exists(string c | - start+1 = this.getText().indexOf(c) | + exists(string c | start + 1 = this.getText().indexOf(c) | c = "}" or c = ":" or c = "!" or c = "." ) } /** Whether this format string has implicitly numbered fields */ - predicate isImplicitlyNumbered() { - this.implicitlyNumberedField(_, _) - } + predicate isImplicitlyNumbered() { this.implicitlyNumberedField(_, _) } /** Whether this format string has explicitly numbered fields */ - predicate isExplicitlyNumbered() { - exists(this.fieldId(_, _).toInt()) - } - + predicate isExplicitlyNumbered() { exists(this.fieldId(_, _).toInt()) } } predicate brace_sequence(PossibleAdvancedFormatString fmt, int index, int len) { - exists(string text | - text = fmt.getText() | - text.charAt(index) = "{" and not text.charAt(index-1) = "{" and len = 1 + exists(string text | text = fmt.getText() | + text.charAt(index) = "{" and not text.charAt(index - 1) = "{" and len = 1 or - text.charAt(index) = "{" and text.charAt(index-1) = "{" and brace_sequence(fmt, index-1, len-1) + text.charAt(index) = "{" and + text.charAt(index - 1) = "{" and + brace_sequence(fmt, index - 1, len - 1) ) } predicate escaped_brace(PossibleAdvancedFormatString fmt, int index) { - exists(int len | - brace_sequence(fmt, index, len) | - len % 2 = 0 - ) + exists(int len | brace_sequence(fmt, index, len) | len % 2 = 0) } predicate escaping_brace(PossibleAdvancedFormatString fmt, int index) { - escaped_brace(fmt, index+1) + escaped_brace(fmt, index + 1) } private predicate inner_brace_pair(PossibleAdvancedFormatString fmt, int start, int end) { not escaping_brace(fmt, start) and not escaped_brace(fmt, start) and fmt.getText().charAt(start) = "{" and - exists(string pair | pair = fmt.getText().suffix(start).regexpCapture("(?s)(\\{([^{}]|\\{\\{)*+\\}).*", 1) | + exists(string pair | + pair = fmt.getText().suffix(start).regexpCapture("(?s)(\\{([^{}]|\\{\\{)*+\\}).*", 1) + | end = start + pair.length() ) } private predicate brace_pair(PossibleAdvancedFormatString fmt, int start, int end) { - inner_brace_pair(fmt, start, end) - or - not escaping_brace(fmt, start) and - not escaped_brace(fmt, start) and - exists(string prefix, string postfix, int innerstart, int innerend | - brace_pair(fmt, innerstart, innerend) and - prefix = fmt.getText().regexpFind("\\{([^{}]|\\{\\{)+\\{", _, start) and - innerstart = start+prefix.length()-1 and - postfix = fmt.getText().regexpFind("\\}([^{}]|\\}\\})*\\}", _, innerend-1) and - end = innerend + postfix.length()-1 - ) + inner_brace_pair(fmt, start, end) + or + not escaping_brace(fmt, start) and + not escaped_brace(fmt, start) and + exists(string prefix, string postfix, int innerstart, int innerend | + brace_pair(fmt, innerstart, innerend) and + prefix = fmt.getText().regexpFind("\\{([^{}]|\\{\\{)+\\{", _, start) and + innerstart = start + prefix.length() - 1 and + postfix = fmt.getText().regexpFind("\\}([^{}]|\\}\\})*\\}", _, innerend - 1) and + end = innerend + postfix.length() - 1 + ) } private predicate advanced_format_call(Call format_expr, PossibleAdvancedFormatString fmt, int args) { - exists(CallNode call | - call = format_expr.getAFlowNode() | - call.getFunction().pointsTo(Value::named("format")) and call.getArg(0).pointsTo(_, fmt.getAFlowNode()) and + exists(CallNode call | call = format_expr.getAFlowNode() | + call.getFunction().pointsTo(Value::named("format")) and + call.getArg(0).pointsTo(_, fmt.getAFlowNode()) and args = count(format_expr.getAnArg()) - 1 or call.getFunction().(AttrNode).getObject("format").pointsTo(_, fmt.getAFlowNode()) and @@ -116,26 +106,14 @@ private predicate advanced_format_call(Call format_expr, PossibleAdvancedFormatS } class AdvancedFormatString extends PossibleAdvancedFormatString { - - AdvancedFormatString() { - advanced_format_call(_, this, _) - } - + AdvancedFormatString() { advanced_format_call(_, this, _) } } class AdvancedFormattingCall extends Call { - - AdvancedFormattingCall() { - advanced_format_call(this, _, _) - } + AdvancedFormattingCall() { advanced_format_call(this, _, _) } /** Count of the arguments actually provided */ - int providedArgCount() { - advanced_format_call(this, _, result) - } - - AdvancedFormatString getAFormat() { - advanced_format_call(this, result, _) - } + int providedArgCount() { advanced_format_call(this, _, result) } + AdvancedFormatString getAFormat() { advanced_format_call(this, result, _) } } diff --git a/python/ql/src/Expressions/IsComparisons.qll b/python/ql/src/Expressions/IsComparisons.qll index bf9d8bb71db..8b0fc79a2b1 100644 --- a/python/ql/src/Expressions/IsComparisons.qll +++ b/python/ql/src/Expressions/IsComparisons.qll @@ -1,9 +1,9 @@ import python - predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) { exists(CompareNode fcomp | fcomp = comp.getAFlowNode() | - fcomp.operands(left, op, right) and (op instanceof Is or op instanceof IsNot) + fcomp.operands(left, op, right) and + (op instanceof Is or op instanceof IsNot) ) } @@ -12,8 +12,7 @@ predicate overrides_eq_or_cmp(ClassValue c) { or c.declaresAttribute("__eq__") and not c = Value::named("object") or - exists(ClassValue sup | - sup = c.getASuperType() and not sup = Value::named("object") | + exists(ClassValue sup | sup = c.getASuperType() and not sup = Value::named("object") | sup.declaresAttribute("__eq__") ) or @@ -29,58 +28,56 @@ predicate probablySingleton(ClassValue cls) { predicate invalid_to_use_is_portably(ClassValue c) { overrides_eq_or_cmp(c) and // Exclude type/builtin-function/bool as it is legitimate to compare them using 'is' but they implement __eq__ - not c = Value::named("type") and not c = ClassValue::builtinFunction() and not c = Value::named("bool") and + not c = Value::named("type") and + not c = ClassValue::builtinFunction() and + not c = Value::named("bool") and // OK to compare with 'is' if a singleton not probablySingleton(c) } predicate simple_constant(ControlFlowNode f) { - exists(Value val | f.pointsTo(val) | val = Value::named("True") or val = Value::named("False") or val = Value::named("None")) + exists(Value val | f.pointsTo(val) | + val = Value::named("True") or val = Value::named("False") or val = Value::named("None") + ) } private predicate cpython_interned_value(Expr e) { exists(string text | text = e.(StrConst).getText() | - text.length() = 0 or + text.length() = 0 + or text.length() = 1 and text.regexpMatch("[U+0000-U+00ff]") - ) - or - exists(int i | - i = e.(IntegerLiteral).getN().toInt() | - -5 <= i and i <= 256 ) or + exists(int i | i = e.(IntegerLiteral).getN().toInt() | -5 <= i and i <= 256) + or exists(Tuple t | t = e and not exists(t.getAnElt())) } -/** The set of values that can be expected to be interned across +/** + * The set of values that can be expected to be interned across * the main implementations of Python. PyPy, Jython, etc tend to * follow CPython, but it varies, so this is a best guess. */ private predicate universally_interned_value(Expr e) { - e.(IntegerLiteral).getN().toInt() = 0 - or - exists(Tuple t | t = e and not exists(t.getAnElt())) - or - e.(StrConst).getText() = "" + e.(IntegerLiteral).getN().toInt() = 0 + or + exists(Tuple t | t = e and not exists(t.getAnElt())) + or + e.(StrConst).getText() = "" } predicate cpython_interned_constant(Expr e) { - exists(Expr const | - e.pointsTo(_, const) | - cpython_interned_value(const) - ) + exists(Expr const | e.pointsTo(_, const) | cpython_interned_value(const)) } predicate universally_interned_constant(Expr e) { - exists(Expr const | - e.pointsTo(_, const) | - universally_interned_value(const) - ) + exists(Expr const | e.pointsTo(_, const) | universally_interned_value(const)) } private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1, ClassValue cls2) { exists(ControlFlowNode op1, ControlFlowNode op2 | - comparison_using_is(comp, op1, op, op2) or comparison_using_is(comp, op2, op, op1) | + comparison_using_is(comp, op1, op, op2) or comparison_using_is(comp, op2, op, op1) + | op1.inferredValue().getClass() = cls1 and op2.inferredValue().getClass() = cls2 ) @@ -89,15 +86,17 @@ private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1, private predicate comparison_one_type(Compare comp, Cmpop op, ClassValue cls) { not comparison_both_types(comp, _, _, _) and exists(ControlFlowNode operand | - comparison_using_is(comp, operand, op, _) or comparison_using_is(comp, _, op, operand) | - operand.inferredValue().getClass() = cls + comparison_using_is(comp, operand, op, _) or comparison_using_is(comp, _, op, operand) + | + operand.inferredValue().getClass() = cls ) } predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) { // OK to use 'is' when defining '__eq__' - not exists(Function eq | eq.getName() = "__eq__" or eq.getName() = "__ne__" | eq = comp.getScope().getScope*()) - and + not exists(Function eq | eq.getName() = "__eq__" or eq.getName() = "__ne__" | + eq = comp.getScope().getScope*() + ) and ( comparison_one_type(comp, op, cls) and invalid_to_use_is_portably(cls) or @@ -105,32 +104,32 @@ predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) invalid_to_use_is_portably(cls) and invalid_to_use_is_portably(other) ) - ) - and + ) and // OK to use 'is' when comparing items from a known set of objects not exists(Expr left, Expr right, Value val | comp.compares(left, op, right) and - exists(ImmutableLiteral il | il.getLiteralValue() = val) | + exists(ImmutableLiteral il | il.getLiteralValue() = val) + | left.pointsTo(val) and right.pointsTo(val) or // Simple constant in module, probably some sort of sentinel exists(AstNode origin | - not left.pointsTo(_) and right.pointsTo(val, origin) and + not left.pointsTo(_) and + right.pointsTo(val, origin) and origin.getScope().getEnclosingModule() = comp.getScope().getEnclosingModule() ) - ) - and + ) and // OK to use 'is' when comparing with a member of an enum not exists(Expr left, Expr right, AstNode origin | comp.compares(left, op, right) and - enum_member(origin) | + enum_member(origin) + | left.pointsTo(_, origin) or right.pointsTo(_, origin) ) } private predicate enum_member(AstNode obj) { - exists(ClassValue cls, AssignStmt asgn | - cls.getASuperType().getName() = "Enum" | + exists(ClassValue cls, AssignStmt asgn | cls.getASuperType().getName() = "Enum" | cls.getScope() = asgn.getScope() and asgn.getValue() = obj ) diff --git a/python/ql/src/Expressions/RedundantComparison.qll b/python/ql/src/Expressions/RedundantComparison.qll index 64f80ce31b5..7c2d9857849 100644 --- a/python/ql/src/Expressions/RedundantComparison.qll +++ b/python/ql/src/Expressions/RedundantComparison.qll @@ -1,27 +1,22 @@ import python class RedundantComparison extends Compare { - RedundantComparison() { exists(Expr left, Expr right | - this.compares(left, _, right) - and + this.compares(left, _, right) and same_variable(left, right) ) } - + predicate maybeMissingSelf() { exists(Name left | this.compares(left, _, _) and not this.isConstant() and exists(Class cls | left.getScope().getScope() = cls | - exists(SelfAttribute sa | sa.getName() = left.getId() | - sa.getClass() = cls - ) + exists(SelfAttribute sa | sa.getName() = left.getId() | sa.getClass() = cls) ) ) } - } private predicate same_variable(Expr left, Expr right) { @@ -36,11 +31,14 @@ private predicate name_in_comparison(Compare comp, Name n, Variable v) { private predicate same_name(Name n1, Name n2) { n1 != n2 and - exists(Compare comp, Variable v | name_in_comparison(comp, n1, v) and name_in_comparison(comp, n2, v)) + exists(Compare comp, Variable v | + name_in_comparison(comp, n1, v) and name_in_comparison(comp, n2, v) + ) } private predicate same_attribute(Attribute a1, Attribute a2) { a1 != a2 and exists(Compare comp | comp.contains(a1) and comp.contains(a2)) and - a1.getName() = a2.getName() and same_name(a1.getObject(), a2.getObject()) + a1.getName() = a2.getName() and + same_name(a1.getObject(), a2.getObject()) } diff --git a/python/ql/src/Lexical/CommentedOutCode.qll b/python/ql/src/Lexical/CommentedOutCode.qll index dbb12867466..e8076092ded 100644 --- a/python/ql/src/Lexical/CommentedOutCode.qll +++ b/python/ql/src/Lexical/CommentedOutCode.qll @@ -1,6 +1,5 @@ import python - private predicate def_statement(Comment c) { c.getText().regexpMatch("#(\\S*\\s+)?def\\s.*\\(.*\\).*:\\s*(#.*)?") } @@ -12,7 +11,7 @@ private predicate if_statement(Comment c) { } private predicate for_statement(Comment c) { - c.getText().regexpMatch("#(\\S*\\s+)?for\\s.*\\sin\\s.*:\\s*(#.*)?") + c.getText().regexpMatch("#(\\S*\\s+)?for\\s.*\\sin\\s.*:\\s*(#.*)?") } private predicate with_statement(Comment c) { @@ -20,11 +19,11 @@ private predicate with_statement(Comment c) { } private predicate try_statement(Comment c) { - c.getText().regexpMatch("#(\\S*\\s+)?try:\\s*(#.*)?") + c.getText().regexpMatch("#(\\S*\\s+)?try:\\s*(#.*)?") or c.getText().regexpMatch("#(\\S*\\s+)?except\\s*(\\w+\\s*(\\sas\\s+\\w+\\s*)?)?:\\s*(#.*)?") or - c.getText().regexpMatch("#(\\S*\\s+)?finally:\\s*(#.*)?") + c.getText().regexpMatch("#(\\S*\\s+)?finally:\\s*(#.*)?") } private int indentation(Comment c) { @@ -39,18 +38,16 @@ private predicate class_statement(Comment c) { c.getText().regexpMatch("#(\\S*\\s+)?class\\s+\\w+.*:\\s*(#.*)?") } -private predicate triple_quote(Comment c) { - c.getText().regexpMatch("#.*(\"\"\"|''').*") -} +private predicate triple_quote(Comment c) { c.getText().regexpMatch("#.*(\"\"\"|''').*") } private predicate triple_quoted_string_part(Comment start, Comment end) { - triple_quote(start) and end = start - or - exists(Comment mid | + triple_quote(start) and end = start + or + exists(Comment mid | triple_quoted_string_part(start, mid) and end = non_empty_following(mid) and not triple_quote(end) - ) + ) } private predicate maybe_code(Comment c) { @@ -59,41 +56,37 @@ private predicate maybe_code(Comment c) { commented_out_comment(c) } -private predicate commented_out_comment(Comment c) { - c.getText().regexpMatch("#+\\s+#.*") -} +private predicate commented_out_comment(Comment c) { c.getText().regexpMatch("#+\\s+#.*") } private int scope_start(Comment start) { ( - def_statement(start) or - class_statement(start) - ) - and - result = indentation(start) - and + def_statement(start) or + class_statement(start) + ) and + result = indentation(start) and not non_code(start) } private int block_start(Comment start) { ( - if_statement(start) or - for_statement(start) or - try_statement(start) or - with_statement(start) - ) - and - result = indentation(start) - and + if_statement(start) or + for_statement(start) or + try_statement(start) or + with_statement(start) + ) and + result = indentation(start) and not non_code(start) } private int scope_doc_string_part(Comment start, Comment end) { result = scope_start(start) and - triple_quote(end) and end = non_empty_following(start) + triple_quote(end) and + end = non_empty_following(start) or - exists(Comment mid | + exists(Comment mid | result = scope_doc_string_part(start, mid) and - end = non_empty_following(mid) | + end = non_empty_following(mid) + | not triple_quote(end) ) } @@ -101,15 +94,16 @@ private int scope_doc_string_part(Comment start, Comment end) { private int scope_part(Comment start, Comment end) { result = scope_start(start) and end = start or - exists(Comment mid | + exists(Comment mid | result = scope_doc_string_part(start, mid) and end = non_empty_following(mid) and triple_quote(end) ) or - exists(Comment mid | + exists(Comment mid | result = scope_part(start, mid) and - end = non_empty_following(mid) | + end = non_empty_following(mid) + | indentation(end) > result ) } @@ -119,9 +113,10 @@ private int block_part(Comment start, Comment end) { end = non_empty_following(start) and indentation(end) > result or - exists(Comment mid | + exists(Comment mid | result = block_part(start, mid) and - end = non_empty_following(mid) | + end = non_empty_following(mid) + | indentation(end) > result or result = block_start(end) @@ -145,13 +140,11 @@ private predicate commented_out_code(Comment c) { } private predicate commented_out_code_part(Comment start, Comment end) { - commented_out_code(start) and end = start and - not exists(Comment prev | - non_empty_following(prev) = start | - commented_out_code(prev) - ) + commented_out_code(start) and + end = start and + not exists(Comment prev | non_empty_following(prev) = start | commented_out_code(prev)) or - exists(Comment mid | + exists(Comment mid | commented_out_code_part(start, mid) and non_empty_following(mid) = end and commented_out_code(end) @@ -167,12 +160,7 @@ private predicate commented_out_code_block(Comment start, Comment end) { /* A single line comment that appears to be commented out code */ class CommentedOutCodeLine extends Comment { - - CommentedOutCodeLine () { - exists(CommentedOutCodeBlock b | - b.contains(this) - ) - } + CommentedOutCodeLine() { exists(CommentedOutCodeBlock b | b.contains(this)) } /* Whether this commented-out code line is likely to be example code embedded in a larger comment. */ predicate maybeExampleCode() { @@ -181,19 +169,13 @@ class CommentedOutCodeLine extends Comment { block.maybeExampleCode() ) } - } /** A block of comments that appears to be commented out code */ class CommentedOutCodeBlock extends @py_comment { - - CommentedOutCodeBlock() { - commented_out_code_block(this, _) - } + CommentedOutCodeBlock() { commented_out_code_block(this, _) } - string toString() { - result = "Commented out code" - } + string toString() { result = "Commented out code" } /** Whether this commented-out code block contains the comment c */ predicate contains(Comment c) { @@ -207,28 +189,22 @@ class CommentedOutCodeBlock extends @py_comment { } /** The length of this comment block (in comments) */ - int length() { - result = count(Comment c | this.contains(c)) - } + int length() { result = count(Comment c | this.contains(c)) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { - ((Comment)this).getLocation().hasLocationInfo(filepath, bl, bc, _, _) - and - exists(Comment end | - commented_out_code_block(this, end) | + this.(Comment).getLocation().hasLocationInfo(filepath, bl, bc, _, _) and + exists(Comment end | commented_out_code_block(this, end) | end.getLocation().hasLocationInfo(_, _, _, el, ec) ) } /** Whether this commented-out code block is likely to be example code embedded in a larger comment. */ predicate maybeExampleCode() { - exists(CommentBlock block | - block.contains((Comment)this) | + exists(CommentBlock block | block.contains(this.(Comment)) | exists(int all_code | - all_code = sum (CommentedOutCodeBlock code | block.contains((Comment)code) | code.length()) - and + all_code = sum(CommentedOutCodeBlock code | block.contains(code.(Comment)) | code.length()) and /* This ratio may need fine tuning */ - block.length() > all_code*2 + block.length() > all_code * 2 ) ) } @@ -239,13 +215,14 @@ private predicate word_pair(Comment c, string s1, string s2) { exists(int i1, int i2, int o1, int o2 | s1 = c.getText().regexpFind("\\w+", i1, o1) and s2 = c.getText().regexpFind("\\w+", i2, o2) and - i2 = i1 + 1 and + i2 = i1 + 1 and c.getText().prefix(o1).regexpMatch("[^'\"]*") and c.getText().substring(o1 + s1.length(), o2).regexpMatch("\\s+") ) } -/** The comment c cannot be code if it contains a word pair "word1 word2" and +/** + * The comment c cannot be code if it contains a word pair "word1 word2" and * either: * 1. word1 is not a keyword and word2 is not an operator: * "x is" could be code, "return y" could be code, but "isnt code" cannot be code. @@ -257,48 +234,44 @@ private predicate non_code(Comment c) { exists(string word1, string word2 | word_pair(c, word1, word2) and not word2 = operator_keyword() - | + | not word1 = a_keyword() or word1 = keyword_requiring_colon() and not c.getText().matches("%:%") ) and /* Except comments of the form: # (maybe code) # some comment */ - not c.getText().regexpMatch("#\\S+\\s.*#.*") + not c.getText().regexpMatch("#\\S+\\s.*#.*") or /* Don't count doctests as code */ - c.getText().matches("%>>>%") or c.getText().matches("%...%") + c.getText().matches("%>>>%") + or + c.getText().matches("%...%") } -private predicate filler(Comment c) { - c.getText().regexpMatch("#+[\\s*#-_=+]*") -} +private predicate filler(Comment c) { c.getText().regexpMatch("#+[\\s*#-_=+]*") } -/** Gets the first non empty comment following c */ +/** Gets the first non empty comment following c */ private Comment non_empty_following(Comment c) { - not empty(result) and - ( + not empty(result) and + ( result = empty_following(c).getFollowing() or - not empty(c) and result = c.getFollowing() - ) + not empty(c) and result = c.getFollowing() + ) } /* Helper for non_empty_following() */ private Comment empty_following(Comment c) { not empty(c) and - empty(result) - and - exists(Comment prev | - result = prev.getFollowing() | + empty(result) and + exists(Comment prev | result = prev.getFollowing() | prev = c or prev = empty_following(c) ) } -private predicate empty(Comment c) { - c.getText().regexpMatch("#+\\s*") -} +private predicate empty(Comment c) { c.getText().regexpMatch("#+\\s*") } /* A comment following code on the same line */ private predicate endline_comment(Comment c) { @@ -315,21 +288,40 @@ private predicate file_or_url(Comment c) { } private string operator_keyword() { - result = "import" or result = "and" or result = "is" or result = "or" or result = "in" or result = "not" or result = "as" + result = "import" or + result = "and" or + result = "is" or + result = "or" or + result = "in" or + result = "not" or + result = "as" } private string keyword_requiring_colon() { - result = "try" or result = "while" or result = "elif" or result = "else" or result = "if" or - result = "except" or result = "def" or result = "class" + result = "try" or + result = "while" or + result = "elif" or + result = "else" or + result = "if" or + result = "except" or + result = "def" or + result = "class" } - + private string other_keyword() { - result = "del" or result = "lambda" or result = "from" or - result = "global" or result = "with" or result = "assert" or - result = "yield" or result = "finally" or - result = "print" or - result = "exec" or result = "raise" or - result = "return" or result = "for" + result = "del" or + result = "lambda" or + result = "from" or + result = "global" or + result = "with" or + result = "assert" or + result = "yield" or + result = "finally" or + result = "print" or + result = "exec" or + result = "raise" or + result = "return" or + result = "for" } private string a_keyword() { diff --git a/python/ql/src/Metrics/Internal/Extents.qll b/python/ql/src/Metrics/Internal/Extents.qll index 283f1fb7c30..9fb12bb244c 100644 --- a/python/ql/src/Metrics/Internal/Extents.qll +++ b/python/ql/src/Metrics/Internal/Extents.qll @@ -15,10 +15,10 @@ import python * including the body (if any), as opposed to the location of its name only. */ class RangeFunction extends Function { - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - super.getLocation().hasLocationInfo(path, sl, sc, _, _) - and this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) - } + predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + super.getLocation().hasLocationInfo(path, sl, sc, _, _) and + this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) + } } /** @@ -26,8 +26,8 @@ class RangeFunction extends Function { * including the body (if any), as opposed to the location of its name only. */ class RangeClass extends Class { - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - super.getLocation().hasLocationInfo(path, sl, sc, _, _) - and this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) - } -} \ No newline at end of file + predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + super.getLocation().hasLocationInfo(path, sl, sc, _, _) and + this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) + } +} diff --git a/python/ql/src/Testing/Mox.qll b/python/ql/src/Testing/Mox.qll index c4455c391e8..0c26d2ef899 100644 --- a/python/ql/src/Testing/Mox.qll +++ b/python/ql/src/Testing/Mox.qll @@ -2,15 +2,14 @@ import python /** Whether `mox` or `.StubOutWithMock()` is used in thin module `m`. */ predicate useOfMoxInModule(Module m) { - exists(ModuleObject mox | - mox.getName() = "mox" or mox.getName() = "mox3.mox" | - exists(ControlFlowNode use | + exists(ModuleObject mox | mox.getName() = "mox" or mox.getName() = "mox3.mox" | + exists(ControlFlowNode use | use.refersTo(mox) and use.getScope().getEnclosingModule() = m ) ) or - exists(Call call| + exists(Call call | call.getFunc().(Attribute).getName() = "StubOutWithMock" and call.getEnclosingModule() = m ) diff --git a/python/ql/src/analysis/CrossProjectDefinitions.qll b/python/ql/src/analysis/CrossProjectDefinitions.qll index a60228f1976..5b9a904e794 100644 --- a/python/ql/src/analysis/CrossProjectDefinitions.qll +++ b/python/ql/src/analysis/CrossProjectDefinitions.qll @@ -1,46 +1,42 @@ /** * Symbols for crosss-project jump-to-definition resolution. */ - import python +import python import semmle.python.pointsto.PointsTo private newtype TSymbol = - TModule(Module m) - or + TModule(Module m) or TMember(Symbol outer, string part) { - exists(Object o | - outer.resolvesTo() = o | + exists(Object o | outer.resolvesTo() = o | o.(ModuleObject).hasAttribute(part) or o.(ClassObject).hasAttribute(part) ) } -/** A "symbol" referencing an object in another module - * Symbols are represented by the module name and the dotted name by which the +/** + * A "symbol" referencing an object in another module + * Symbols are represented by the module name and the dotted name by which the * object would be referred to in that module. * For example for the code: * ``` * class C: * def m(self): pass * ``` - * If the code were in a module `mod`, + * If the code were in a module `mod`, * then symbol for the method `m` would be "mod/C.m" */ class Symbol extends TSymbol { - string toString() { - exists(Module m | - this = TModule(m) and result = m.getName() - ) - or + exists(Module m | this = TModule(m) and result = m.getName()) + or exists(TModule outer, string part | this = TMember(outer, part) and outer = TModule(_) and result = outer.(Symbol).toString() + "/" + part ) - or + or exists(TMember outer, string part | this = TMember(outer, part) and outer = TMember(_, _) and @@ -52,8 +48,7 @@ class Symbol extends TSymbol { AstNode find() { this = TModule(result) or - exists(Symbol s, string name | - this = TMember(s, name) | + exists(Symbol s, string name | this = TMember(s, name) | exists(ClassObject cls | s.resolvesTo() = cls and cls.attributeRefersTo(name, _, result.getAFlowNode()) @@ -66,47 +61,43 @@ class Symbol extends TSymbol { ) } - /** Find the class or module `Object` that this `Symbol` refers to, if + /** + * Find the class or module `Object` that this `Symbol` refers to, if * this `Symbol` refers to a class or module. */ Object resolvesTo() { this = TModule(result.(ModuleObject).getModule()) or exists(Symbol s, string name, Object o | - this = TMember(s, name) and + this = TMember(s, name) and o = s.resolvesTo() and result = attribute_in_scope(o, name) ) } - /** Gets the `Module` for the module part of this `Symbol`. + /** + * Gets the `Module` for the module part of this `Symbol`. * For example, this would return the `os` module for the `Symbol` "os/environ". */ Module getModule() { this = TModule(result) or - exists(Symbol outer | - this = TMember(outer, _) and result = outer.getModule() - ) + exists(Symbol outer | this = TMember(outer, _) and result = outer.getModule()) } /** Gets the `Symbol` that is the named member of this `Symbol`. */ - Symbol getMember(string name) { - result = TMember(this, name) - } - + Symbol getMember(string name) { result = TMember(this, name) } } /* Helper for `Symbol`.resolvesTo() */ private Object attribute_in_scope(Object obj, string name) { - exists(ClassObject cls | - cls = obj | + exists(ClassObject cls | cls = obj | cls.lookupAttribute(name) = result and result.(ControlFlowNode).getScope() = cls.getPyClass() ) or - exists(ModuleObject mod | - mod = obj | - mod.attr(name) = result and result.(ControlFlowNode).getScope() = mod.getModule() - and not result.(ControlFlowNode).isEntryNode() + exists(ModuleObject mod | mod = obj | + mod.attr(name) = result and + result.(ControlFlowNode).getScope() = mod.getModule() and + not result.(ControlFlowNode).isEntryNode() ) } diff --git a/python/ql/src/analysis/DefinitionTracking.qll b/python/ql/src/analysis/DefinitionTracking.qll index 2fe097b1b9e..6216142af49 100644 --- a/python/ql/src/analysis/DefinitionTracking.qll +++ b/python/ql/src/analysis/DefinitionTracking.qll @@ -1,35 +1,22 @@ /** * Definition tracking for jump-to-defn query. */ -import python +import python import semmle.python.pointsto.PointsTo private newtype TDefinition = - TLocalDefinition(AstNode a) { - a instanceof Expr or a instanceof Stmt or a instanceof Module - } + TLocalDefinition(AstNode a) { a instanceof Expr or a instanceof Stmt or a instanceof Module } /** A definition for the purposes of jump-to-definition. */ class Definition extends TLocalDefinition { + string toString() { result = "Definition " + this.getAstNode().getLocation().toString() } + AstNode getAstNode() { this = TLocalDefinition(result) } - string toString() { - result = "Definition " + this.getAstNode().getLocation().toString() - } - - AstNode getAstNode() { - this = TLocalDefinition(result) - } - - Module getModule() { - result = this.getAstNode().getScope().getEnclosingModule() - } - - Location getLocation() { - result = this.getAstNode().getLocation() - } + Module getModule() { result = this.getAstNode().getScope().getEnclosingModule() } + Location getLocation() { result = this.getAstNode().getLocation() } } private predicate jump_to_defn(ControlFlowNode use, Definition defn) { @@ -112,7 +99,7 @@ predicate uni_edged_phi_defn(SingleSuccessorGuard uniphi, Definition defn) { ssa_variable_defn(uniphi.getInput(), defn) } -pragma [noinline] +pragma[noinline] private predicate ssa_node_defn(EssaNodeDefinition def, Definition defn) { assignment_jump_to_defn(def, defn) or @@ -130,7 +117,7 @@ private predicate assignment_jump_to_defn(AssignmentDefinition def, Definition d defn = TLocalDefinition(def.getValue().getNode()) } -pragma [noinline] +pragma[noinline] private predicate ssa_node_refinement_defn(EssaNodeRefinement def, Definition defn) { method_callsite_defn(def, defn) or @@ -147,16 +134,13 @@ private predicate ssa_node_refinement_defn(EssaNodeRefinement def, Definition de uni_edged_phi_defn(def, defn) } - /* Definition for parameter. `def foo(param): ...` */ private predicate parameter_defn(ParameterDefinition def, Definition defn) { defn.getAstNode() = def.getDefiningNode().getNode() } /* Definition for deletion: `del name` */ -private predicate delete_defn(DeletionDefinition def, Definition defn) { - none() -} +private predicate delete_defn(DeletionDefinition def, Definition defn) { none() } /* Implicit "defn" of the names of submodules at the start of an `__init__.py` file. */ private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Definition defn) { @@ -165,13 +149,16 @@ private predicate implicit_submodule_defn(ImplicitSubModuleDefinition def, Defin mod = package.submodule(def.getSourceVariable().getName()) and defn.getAstNode() = mod.getModule() ) - } -/* Helper for scope_entry_value_transfer(...). - * Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters +/* + * Helper for scope_entry_value_transfer(...). + * Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters */ -private predicate scope_entry_value_transfer_at_callsite(EssaVariable pred_var, ScopeEntryDefinition succ_def) { + +private predicate scope_entry_value_transfer_at_callsite( + EssaVariable pred_var, ScopeEntryDefinition succ_def +) { exists(CallNode callsite, FunctionObject f | f.getACall() = callsite and pred_var.getSourceVariable() = succ_def.getSourceVariable() and @@ -181,8 +168,7 @@ private predicate scope_entry_value_transfer_at_callsite(EssaVariable pred_var, } /* Model the transfer of values at scope-entry points. Transfer from `pred_var, pred_context` to `succ_def, succ_context` */ -private -predicate scope_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition succ_def) { +private predicate scope_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition succ_def) { BaseFlow::scope_entry_value_transfer_from_earlier(pred_var, _, succ_def, _) or scope_entry_value_transfer_at_callsite(pred_var, succ_def) @@ -191,8 +177,7 @@ predicate scope_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition } /* Helper for scope_entry_value_transfer */ -private -predicate class_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition succ_def) { +private predicate class_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition succ_def) { exists(ImportTimeScope scope, ControlFlowNode class_def | class_def = pred_var.getAUse() and scope.entryEdge(class_def, succ_def.getDefiningNode()) and @@ -201,7 +186,7 @@ predicate class_entry_value_transfer(EssaVariable pred_var, ScopeEntryDefinition } /* Definition for implicit variable declarations at scope-entry. */ -pragma [noinline] +pragma[noinline] private predicate scope_entry_defn(ScopeEntryDefinition def, Definition defn) { /* Transfer from another scope */ exists(EssaVariable var | @@ -210,10 +195,12 @@ private predicate scope_entry_defn(ScopeEntryDefinition def, Definition defn) { ) } -/* Definition for a variable (possibly) redefined by a call: +/* + * Definition for a variable (possibly) redefined by a call: * Just assume that call does not define variable */ -pragma [noinline] + +pragma[noinline] private predicate callsite_defn(CallsiteRefinement def, Definition defn) { ssa_variable_defn(def.getInput(), defn) } @@ -225,22 +212,27 @@ private predicate method_callsite_defn(MethodCallsiteRefinement def, Definition } /** Helpers for import_star_defn */ -pragma [noinline] -private predicate module_and_name_for_import_star(ModuleObject mod, string name, ImportStarRefinement def) { +pragma[noinline] +private predicate module_and_name_for_import_star( + ModuleObject mod, string name, ImportStarRefinement def +) { exists(ImportStarNode im_star | module_and_name_for_import_star_helper(mod, name, im_star, def) and mod.exports(name) ) } -pragma [noinline] -private predicate module_and_name_for_import_star_helper(ModuleObject mod, string name, ImportStarNode im_star, ImportStarRefinement def) { +pragma[noinline] +private predicate module_and_name_for_import_star_helper( + ModuleObject mod, string name, ImportStarNode im_star, ImportStarRefinement def +) { im_star = def.getDefiningNode() and im_star.getModule().refersTo(mod) and name = def.getSourceVariable().getName() } - /** Holds if `def` is technically a defn of `var`, but the `from ... import *` does not in fact define `var` */ -pragma [noinline] + +/** Holds if `def` is technically a defn of `var`, but the `from ... import *` does not in fact define `var` */ +pragma[noinline] private predicate variable_not_redefined_by_import_star(EssaVariable var, ImportStarRefinement def) { var = def.getInput() and exists(ModuleObject mod | @@ -251,8 +243,7 @@ private predicate variable_not_redefined_by_import_star(EssaVariable var, Import /* Definition for `from ... import *` */ private predicate import_star_defn(ImportStarRefinement def, Definition defn) { - exists(ModuleObject mod, string name | - module_and_name_for_import_star(mod, name, def) | + exists(ModuleObject mod, string name | module_and_name_for_import_star(mod, name, def) | /* Attribute from imported module */ scope_jump_to_defn_attribute(mod.getModule(), name, defn) ) @@ -275,18 +266,20 @@ private predicate argument_defn(ArgumentRefinement def, Definition defn) { } /** Attribute deletions have no effect as far as value tracking is concerned. */ -pragma [noinline] +pragma[noinline] private predicate attribute_delete_defn(EssaAttributeDeletion def, Definition defn) { ssa_variable_defn(def.getInput(), defn) } -/* Definition flow for attributes. These mirror the "normal" defn predicates. +/* + * Definition flow for attributes. These mirror the "normal" defn predicates. * For each defn predicate `xxx_defn(XXX def, Definition defn)` * There is an equivalent predicate that tracks the values in attributes: * `xxx_jump_to_defn_attribute(XXX def, string name, Definition defn)` - * */ + */ -/** INTERNAL -- Public for testing only. +/** + * INTERNAL -- Public for testing only. * Holds if the attribute `name` of the ssa variable `var` refers to (`value`, `cls`, `origin`) */ predicate ssa_variable_jump_to_defn_attribute(EssaVariable var, string name, Definition defn) { @@ -316,7 +309,9 @@ private predicate ssa_phi_jump_to_defn_attribute(PhiFunction phi, string name, D /** Helper for ssa_defn_jump_to_defn_attribute */ pragma[noinline] -private predicate ssa_node_jump_to_defn_attribute(EssaNodeDefinition def, string name, Definition defn) { +private predicate ssa_node_jump_to_defn_attribute( + EssaNodeDefinition def, string name, Definition defn +) { assignment_jump_to_defn_attribute(def, name, defn) or self_parameter_jump_to_defn_attribute(def, name, defn) @@ -326,14 +321,18 @@ private predicate ssa_node_jump_to_defn_attribute(EssaNodeDefinition def, string /** Helper for ssa_defn_jump_to_defn_attribute */ pragma[noinline] -private predicate ssa_node_refinement_jump_to_defn_attribute(EssaNodeRefinement def, string name, Definition defn) { +private predicate ssa_node_refinement_jump_to_defn_attribute( + EssaNodeRefinement def, string name, Definition defn +) { attribute_assignment_jump_to_defn_attribute(def, name, defn) or argument_jump_to_defn_attribute(def, name, defn) } pragma[noinline] -private predicate scope_entry_jump_to_defn_attribute(ScopeEntryDefinition def, string name, Definition defn) { +private predicate scope_entry_jump_to_defn_attribute( + ScopeEntryDefinition def, string name, Definition defn +) { exists(EssaVariable var | scope_entry_value_transfer(var, def) and ssa_variable_jump_to_defn_attribute(var, name, defn) @@ -342,9 +341,10 @@ private predicate scope_entry_jump_to_defn_attribute(ScopeEntryDefinition def, s private predicate scope_jump_to_defn_attribute(ImportTimeScope s, string name, Definition defn) { exists(EssaVariable var | - BaseFlow::reaches_exit(var) and var.getScope() = s and + BaseFlow::reaches_exit(var) and + var.getScope() = s and var.getName() = name - | + | ssa_variable_defn(var, defn) ) } @@ -357,22 +357,23 @@ private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Defin ) or /* Instance attributes */ - exists(ClassObject cls | - use.refersTo(_, cls, _) | + exists(ClassObject cls | use.refersTo(_, cls, _) | scope_jump_to_defn_attribute(cls.getPyClass(), name, defn) ) or /* Super attributes */ exists(AttrNode f, SuperBoundMethod sbm, Object function | use = f.getObject(name) and - f.refersTo(sbm) and function = sbm.getFunction(_) and + f.refersTo(sbm) and + function = sbm.getFunction(_) and function.getOrigin() = defn.getAstNode() ) or /* Class or module attribute */ exists(Object obj, Scope scope | use.refersTo(obj) and - scope_jump_to_defn_attribute(scope, name, defn) | + scope_jump_to_defn_attribute(scope, name, defn) + | obj.(ClassObject).getPyClass() = scope or obj.(PythonModuleObject).getModule() = scope @@ -382,18 +383,23 @@ private predicate jump_to_defn_attribute(ControlFlowNode use, string name, Defin } pragma[noinline] -private predicate assignment_jump_to_defn_attribute(AssignmentDefinition def, string name, Definition defn) { +private predicate assignment_jump_to_defn_attribute( + AssignmentDefinition def, string name, Definition defn +) { jump_to_defn_attribute(def.getValue(), name, defn) } pragma[noinline] -private predicate attribute_assignment_jump_to_defn_attribute(AttributeAssignment def, string name, Definition defn) { +private predicate attribute_assignment_jump_to_defn_attribute( + AttributeAssignment def, string name, Definition defn +) { defn.getAstNode() = def.getDefiningNode().getNode() and name = def.getName() or ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn) and not name = def.getName() } -/** Holds if `def` defines the attribute `name` +/** + * Holds if `def` defines the attribute `name` * `def` takes the form `setattr(use, "name")` where `use` is the input to the defn. */ private predicate sets_attribute(ArgumentRefinement def, string name) { @@ -406,31 +412,37 @@ private predicate sets_attribute(ArgumentRefinement def, string name) { } pragma[noinline] -private predicate argument_jump_to_defn_attribute(ArgumentRefinement def, string name, Definition defn) { - if sets_attribute(def, name) then - jump_to_defn(def.getDefiningNode().(CallNode).getArg(2), defn) - else - ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn) +private predicate argument_jump_to_defn_attribute( + ArgumentRefinement def, string name, Definition defn +) { + if sets_attribute(def, name) + then jump_to_defn(def.getDefiningNode().(CallNode).getArg(2), defn) + else ssa_variable_jump_to_defn_attribute(def.getInput(), name, defn) } -/** Gets the (temporally) preceding variable for "self", e.g. `def` is in method foo() and `result` is in `__init__()`. */ +/** Gets the (temporally) preceding variable for "self", e.g. `def` is in method foo() and `result` is in `__init__()`. */ private EssaVariable preceding_self_variable(ParameterDefinition def) { def.isSelf() and exists(Function preceding, Function method | - method = def.getScope() and + method = def.getScope() and // Only methods - preceding.isMethod() and preceding.precedes(method) and - BaseFlow::reaches_exit(result) and result.getSourceVariable().(Variable).isSelf() and + preceding.isMethod() and + preceding.precedes(method) and + BaseFlow::reaches_exit(result) and + result.getSourceVariable().(Variable).isSelf() and result.getScope() = preceding ) } -pragma [noinline] -private predicate self_parameter_jump_to_defn_attribute(ParameterDefinition def, string name, Definition defn) { +pragma[noinline] +private predicate self_parameter_jump_to_defn_attribute( + ParameterDefinition def, string name, Definition defn +) { ssa_variable_jump_to_defn_attribute(preceding_self_variable(def), name, defn) } -/** Gets a definition for 'use'. +/** + * Gets a definition for 'use'. * This exists primarily for testing use `getPreferredDefinition()` instead. */ Definition getADefinition(Expr use) { @@ -441,7 +453,8 @@ Definition getADefinition(Expr use) { not result = TLocalDefinition(use) } -/** Gets the unique definition for 'use', if one can be found. +/** + * Gets the unique definition for 'use', if one can be found. * Helper for the jump-to-definition query. */ Definition getUniqueDefinition(Expr use) { @@ -452,18 +465,13 @@ Definition getUniqueDefinition(Expr use) { not result = TLocalDefinition(use) } - /** Helper class to get suitable locations for attributes */ class NiceLocationExpr extends @py_expr { - - string toString() { - result = this.(Expr).toString() - } + string toString() { result = this.(Expr).toString() } predicate hasLocationInfo(string f, int bl, int bc, int el, int ec) { - /* Attribute location for x.y is that of 'y' so that url does not overlap with that of 'x' */ - exists(int abl, int abc | - this.(Attribute).getLocation().hasLocationInfo(f, abl, abc, el, ec) | + /* Attribute location for x.y is that of 'y' so that url does not overlap with that of 'x' */ + exists(int abl, int abc | this.(Attribute).getLocation().hasLocationInfo(f, abl, abc, el, ec) | bl = el and bc = ec - this.(Attribute).getName().length() + 1 ) or @@ -477,10 +485,8 @@ class NiceLocationExpr extends @py_expr { exists(string name | name = this.(ImportMember).getName() and this.(ImportMember).getLocation().hasLocationInfo(f, _, _, el, ec) and - bl = el and bc = ec-name.length()+1 + bl = el and + bc = ec - name.length() + 1 ) } - } - - From a3bd46d4fe92dc9489e84ce5d0a5d97ff246e8fb Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 20 Mar 2020 16:43:10 +0100 Subject: [PATCH 117/459] Python: Autoformat remaining `.qll`. --- python/ql/src/default.qll | 1 + python/ql/src/external/CodeDuplication.qll | 132 ++++++------ python/ql/src/external/DefectFilter.qll | 73 ++++--- python/ql/src/external/ExternalArtifact.qll | 87 +++----- python/ql/src/external/Thrift.qll | 228 +++++--------------- python/ql/src/external/VCS.qll | 120 +++++------ python/ql/src/python.qll | 1 - python/ql/src/semmle/crypto/Crypto.qll | 126 +++++------ python/ql/src/semmle/files/FileSystem.qll | 1 + 9 files changed, 279 insertions(+), 490 deletions(-) diff --git a/python/ql/src/default.qll b/python/ql/src/default.qll index 99374e13f76..8fa398db399 100644 --- a/python/ql/src/default.qll +++ b/python/ql/src/default.qll @@ -2,4 +2,5 @@ * WARNING: Use of this module is DEPRECATED. * All new queries should use `import python`. */ + import python diff --git a/python/ql/src/external/CodeDuplication.qll b/python/ql/src/external/CodeDuplication.qll index 3178f8d463a..c195d16ae6a 100644 --- a/python/ql/src/external/CodeDuplication.qll +++ b/python/ql/src/external/CodeDuplication.qll @@ -3,10 +3,7 @@ import python /** Gets the relative path of `file`, with backslashes replaced by forward slashes. */ -private -string relativePath(File file) { - result = file.getRelativePath().replaceAll("\\", "/") -} +private string relativePath(File file) { result = file.getRelativePath().replaceAll("\\", "/") } /** * Holds if the `index`-th token of block `copy` is in file `file`, spanning @@ -21,60 +18,42 @@ private predicate tokenLocation(File file, int sl, int sc, int ec, int el, Copy } /** A token block used for detection of duplicate and similar code. */ -class Copy extends @duplication_or_similarity -{ - private - int lastToken() { - result = max(int i | tokens(this, i, _, _, _, _) | i) - } +class Copy extends @duplication_or_similarity { + private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) } /** Gets the index of the token in this block starting at the location `loc`, if any. */ int tokenStartingAt(Location loc) { - tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), - _, _, this, result) + tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), _, _, this, result) } /** Gets the index of the token in this block ending at the location `loc`, if any. */ int tokenEndingAt(Location loc) { - tokenLocation(loc.getFile(), _, _, - loc.getEndLine(), loc.getEndColumn(), this, result) + tokenLocation(loc.getFile(), _, _, loc.getEndLine(), loc.getEndColumn(), this, result) } /** Gets the line on which the first token in this block starts. */ - int sourceStartLine() { - tokens(this, 0, result, _, _, _) - } + int sourceStartLine() { tokens(this, 0, result, _, _, _) } /** Gets the column on which the first token in this block starts. */ - int sourceStartColumn() { - tokens(this, 0, _, result, _, _) - } + int sourceStartColumn() { tokens(this, 0, _, result, _, _) } /** Gets the line on which the last token in this block ends. */ - int sourceEndLine() { - tokens(this, this.lastToken(), _, _, result, _) - } + int sourceEndLine() { tokens(this, this.lastToken(), _, _, result, _) } /** Gets the column on which the last token in this block ends. */ - int sourceEndColumn() { - tokens(this, this.lastToken(), _, _, _, result) - } + int sourceEndColumn() { tokens(this, this.lastToken(), _, _, _, result) } /** Gets the number of lines containing at least (part of) one token in this block. */ - int sourceLines() { - result = this.sourceEndLine() + 1 - this.sourceStartLine() - } + int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() } /** Gets an opaque identifier for the equivalence class of this block. */ - int getEquivalenceClass() { - duplicateCode(this, _, result) or similarCode(this, _, result) - } + int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) } /** Gets the source file in which this block appears. */ File sourceFile() { - exists(string name | - duplicateCode(this, name, _) or similarCode(this, name, _) | - name.replaceAll("\\", "/") = relativePath(result)) + exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) | + name.replaceAll("\\", "/") = relativePath(result) + ) } /** @@ -84,7 +63,9 @@ class Copy extends @duplication_or_similarity * For more information, see * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { sourceFile().getName() = filepath and startline = sourceStartLine() and startcolumn = sourceStartColumn() and @@ -102,7 +83,8 @@ class Copy extends @duplication_or_similarity Copy extendingBlock() { exists(File file, int sl, int sc, int ec, int el | tokenLocation(file, sl, sc, ec, el, this, _) and - tokenLocation(file, sl, sc, ec, el, result, 0)) and + tokenLocation(file, sl, sc, ec, el, result, 0) + ) and this != result } } @@ -113,13 +95,17 @@ class Copy extends @duplication_or_similarity * have the same equivalence class, with `start` being the equivalence class of `start1` and * `start2`, and `end` the equivalence class of `end1` and `end2`. */ -predicate similar_extension(SimilarBlock start1, SimilarBlock start2, SimilarBlock ext1, SimilarBlock ext2, int start, int ext) { +predicate similar_extension( + SimilarBlock start1, SimilarBlock start2, SimilarBlock ext1, SimilarBlock ext2, int start, int ext +) { start1.getEquivalenceClass() = start and start2.getEquivalenceClass() = start and ext1.getEquivalenceClass() = ext and ext2.getEquivalenceClass() = ext and start1 != start2 and - (ext1 = start1 and ext2 = start2 or + ( + ext1 = start1 and ext2 = start2 + or similar_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext) ) } @@ -130,28 +116,29 @@ predicate similar_extension(SimilarBlock start1, SimilarBlock start2, SimilarBlo * have the same equivalence class, with `start` being the equivalence class of `start1` and * `start2`, and `end` the equivalence class of `end1` and `end2`. */ -predicate duplicate_extension(DuplicateBlock start1, DuplicateBlock start2, DuplicateBlock ext1, DuplicateBlock ext2, int start, int ext) { +predicate duplicate_extension( + DuplicateBlock start1, DuplicateBlock start2, DuplicateBlock ext1, DuplicateBlock ext2, int start, + int ext +) { start1.getEquivalenceClass() = start and start2.getEquivalenceClass() = start and ext1.getEquivalenceClass() = ext and ext2.getEquivalenceClass() = ext and start1 != start2 and - (ext1 = start1 and ext2 = start2 or + ( + ext1 = start1 and ext2 = start2 + or duplicate_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext) ) } /** A block of duplicated code. */ -class DuplicateBlock extends Copy, @duplication -{ - override string toString() { - result = "Duplicate code: " + sourceLines() + " duplicated lines." - } +class DuplicateBlock extends Copy, @duplication { + override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." } } /** A block of similar code. */ -class SimilarBlock extends Copy, @similarity -{ +class SimilarBlock extends Copy, @similarity { override string toString() { result = "Similar code: " + sourceLines() + " almost duplicated lines." } @@ -167,8 +154,9 @@ predicate duplicateStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) scope2.contains(stmt2) and duplicateCoversStatement(equivstart, equivend, first, last, stmt1) and duplicateCoversStatement(equivstart, equivend, first, last, stmt2) and - stmt1 != stmt2 and scope1 != scope2 - ) + stmt1 != stmt2 and + scope1 != scope2 + ) } /** @@ -178,8 +166,9 @@ predicate duplicateStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) * and `equivstart` and `equivend` are the equivalence classes of the first and the last * block, respectively. */ -private -predicate duplicateCoversStatement(int equivstart, int equivend, int first, int last, Stmt stmt) { +private predicate duplicateCoversStatement( + int equivstart, int equivend, int first, int last, Stmt stmt +) { exists(DuplicateBlock b1, DuplicateBlock b2, Location startloc, Location endloc | stmt.getLocation() = startloc and stmt.getLastStatement().getLocation() = endloc and @@ -204,13 +193,14 @@ predicate duplicateStatements(Scope scope1, Scope scope2, int duplicate, int tot * Find pairs of scopes that are identical or almost identical */ predicate duplicateScopes(Scope s, Scope other, float percent, string message) { - exists(int total, int duplicate | - duplicateStatements(s, other, duplicate, total) | - percent = 100.0 * duplicate / total and percent >= 80.0 and - if duplicate = total then - message = "All " + total + " statements in " + s.getName() + " are identical in $@." + exists(int total, int duplicate | duplicateStatements(s, other, duplicate, total) | + percent = 100.0 * duplicate / total and + percent >= 80.0 and + if duplicate = total + then message = "All " + total + " statements in " + s.getName() + " are identical in $@." else - message = duplicate + " out of " + total + " statements in " + s.getName() + " are duplicated in $@." + message = + duplicate + " out of " + total + " statements in " + s.getName() + " are duplicated in $@." ) } @@ -219,12 +209,13 @@ predicate duplicateScopes(Scope s, Scope other, float percent, string message) { * respectively, where `scope1` and `scope2` are not the same. */ private predicate similarStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) { - exists(int start, int end, int first, int last | + exists(int start, int end, int first, int last | scope1.contains(stmt1) and scope2.contains(stmt2) and similarCoversStatement(start, end, first, last, stmt1) and similarCoversStatement(start, end, first, last, stmt2) and - stmt1 != stmt2 and scope1 != scope2 + stmt1 != stmt2 and + scope1 != scope2 ) } @@ -235,7 +226,9 @@ private predicate similarStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt * and `equivstart` and `equivend` are the equivalence classes of the first and the last * block, respectively. */ -private predicate similarCoversStatement(int equivstart, int equivend, int first, int last, Stmt stmt) { +private predicate similarCoversStatement( + int equivstart, int equivend, int first, int last, Stmt stmt +) { exists(SimilarBlock b1, SimilarBlock b2, Location startloc, Location endloc | stmt.getLocation() = startloc and stmt.getLastStatement().getLocation() = endloc and @@ -260,13 +253,14 @@ private predicate similarStatements(Scope scope1, Scope scope2, int similar, int * Find pairs of scopes that are similar */ predicate similarScopes(Scope s, Scope other, float percent, string message) { - exists(int total, int similar | - similarStatements(s, other, similar, total) | - percent = 100.0 * similar / total and percent >= 80.0 and - if similar = total then - message = "All statements in " + s.getName() + " are similar in $@." + exists(int total, int similar | similarStatements(s, other, similar, total) | + percent = 100.0 * similar / total and + percent >= 80.0 and + if similar = total + then message = "All statements in " + s.getName() + " are similar in $@." else - message = similar + " out of " + total + " statements in " + s.getName() + " are similar in $@." + message = + similar + " out of " + total + " statements in " + s.getName() + " are similar in $@." ) } @@ -275,7 +269,5 @@ predicate similarScopes(Scope s, Scope other, float percent, string message) { * This is true for blocks of import statements. */ predicate whitelistedLineForDuplication(File f, int line) { - exists(ImportingStmt i | - i.getLocation().getFile() = f and i.getLocation().getStartLine() = line - ) + exists(ImportingStmt i | i.getLocation().getFile() = f and i.getLocation().getStartLine() = line) } diff --git a/python/ql/src/external/DefectFilter.qll b/python/ql/src/external/DefectFilter.qll index e34385acfb8..6d5f75510cf 100644 --- a/python/ql/src/external/DefectFilter.qll +++ b/python/ql/src/external/DefectFilter.qll @@ -10,58 +10,61 @@ import semmle.python.Files * * For more information, see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). */ -external predicate defectResults(int id, string queryPath, string filepath, int startline, - int startcol, int endline, int endcol, string message); +external predicate defectResults( + int id, string queryPath, string filepath, int startline, int startcol, int endline, int endcol, + string message +); /** * A defect query result stored in a dashboard database. */ class DefectResult extends int { + DefectResult() { defectResults(this, _, _, _, _, _, _, _) } - DefectResult() { defectResults(this, _, _, _, _, _, _, _) } + /** Gets the path of the query that reported the result. */ + string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) } - /** Gets the path of the query that reported the result. */ - string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) } + /** Gets the file in which this query result was reported. */ + File getFile() { + exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getName() = path) + } - /** Gets the file in which this query result was reported. */ - File getFile() { - exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getName() = path) - } + /** Gets the file path in which this query result was reported. */ + string getFilePath() { defectResults(this, _, result, _, _, _, _, _) } - /** Gets the file path in which this query result was reported. */ - string getFilePath() { defectResults(this, _, result, _, _, _, _, _) } + /** Gets the line on which the location of this query result starts. */ + int getStartLine() { defectResults(this, _, _, result, _, _, _, _) } - /** Gets the line on which the location of this query result starts. */ - int getStartLine() { defectResults(this, _, _, result, _, _, _, _) } + /** Gets the column on which the location of this query result starts. */ + int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) } - /** Gets the column on which the location of this query result starts. */ - int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) } + /** Gets the line on which the location of this query result ends. */ + int getEndLine() { defectResults(this, _, _, _, _, result, _, _) } - /** Gets the line on which the location of this query result ends. */ - int getEndLine() { defectResults(this, _, _, _, _, result, _, _) } + /** Gets the column on which the location of this query result ends. */ + int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) } - /** Gets the column on which the location of this query result ends. */ - int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) } + /** Gets the message associated with this query result. */ + string getMessage() { defectResults(this, _, _, _, _, _, _, result) } - /** Gets the message associated with this query result. */ - string getMessage() { defectResults(this, _, _, _, _, _, _, result) } - - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - defectResults(this, _, path, sl, sc, el, ec, _) - } - - /** Gets the URL corresponding to the location of this query result. */ - string getURL() { - result = "file://" + getFile().getName() + ":" + getStartLine() + ":" + getStartColumn() + ":" + getEndLine() + ":" + getEndColumn() - } + predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + defectResults(this, _, path, sl, sc, el, ec, _) + } + /** Gets the URL corresponding to the location of this query result. */ + string getURL() { + result = + "file://" + getFile().getName() + ":" + getStartLine() + ":" + getStartColumn() + ":" + + getEndLine() + ":" + getEndColumn() + } } // crude containment by line number only predicate contains(Location l, DefectResult res) { - exists(string path, int bl1, int el1, int bl2, int el2 | - l.hasLocationInfo(path, bl1, _, el1, _) - and res.hasLocationInfo(path, bl2, _, el2, _) - and bl1 <= bl2 and el1 >= el2 - ) + exists(string path, int bl1, int el1, int bl2, int el2 | + l.hasLocationInfo(path, bl1, _, el1, _) and + res.hasLocationInfo(path, bl2, _, el2, _) and + bl1 <= bl2 and + el1 >= el2 + ) } diff --git a/python/ql/src/external/ExternalArtifact.qll b/python/ql/src/external/ExternalArtifact.qll index 9c2fe6a9b66..0ed2c8d4878 100644 --- a/python/ql/src/external/ExternalArtifact.qll +++ b/python/ql/src/external/ExternalArtifact.qll @@ -1,7 +1,6 @@ import python class ExternalDefect extends @externalDefect { - string getQueryPath() { exists(string path | externalDefects(this, path, _, _, _) and @@ -9,95 +8,59 @@ class ExternalDefect extends @externalDefect { ) } - string getMessage() { - externalDefects(this, _, _, result, _) - } + string getMessage() { externalDefects(this, _, _, result, _) } - float getSeverity() { - externalDefects(this, _, _, _, result) - } + float getSeverity() { externalDefects(this, _, _, _, result) } - Location getLocation() { - externalDefects(this,_,result,_,_) - } + Location getLocation() { externalDefects(this, _, result, _, _) } - string toString() { - result = getQueryPath() + ": " + getLocation() + " - " + getMessage() - } + string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getMessage() } } class ExternalMetric extends @externalMetric { + string getQueryPath() { externalMetrics(this, result, _, _) } - string getQueryPath() { - externalMetrics(this, result, _, _) - } + float getValue() { externalMetrics(this, _, _, result) } - float getValue() { - externalMetrics(this, _, _, result) - } + Location getLocation() { externalMetrics(this, _, result, _) } - Location getLocation() { - externalMetrics(this,_,result,_) - } - - string toString() { - result = getQueryPath() + ": " + getLocation() + " - " + getValue() - } + string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getValue() } } class ExternalData extends @externalDataElement { + string getDataPath() { externalData(this, result, _, _) } - string getDataPath() { - externalData(this, result, _, _) - } + string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } - string getQueryPath() { - result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") - } + int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) } - int getNumFields() { - result = 1 + max(int i | externalData(this, _, i, _) | i) - } + string getField(int index) { externalData(this, _, index, result) } - string getField(int index) { - externalData(this, _, index, result) - } + int getFieldAsInt(int index) { result = getField(index).toInt() } - int getFieldAsInt(int index) { - result = getField(index).toInt() - } + float getFieldAsFloat(int index) { result = getField(index).toFloat() } - float getFieldAsFloat(int index) { - result = getField(index).toFloat() - } + date getFieldAsDate(int index) { result = getField(index).toDate() } - date getFieldAsDate(int index) { - result = getField(index).toDate() - } - - string toString() { - result = getQueryPath() + ": " + buildTupleString(0) - } + string toString() { result = getQueryPath() + ": " + buildTupleString(0) } private string buildTupleString(int start) { - (start = getNumFields() - 1 and result = getField(start)) + start = getNumFields() - 1 and result = getField(start) or - (start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start+1)) + start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1) } - } /** * External data with a location, and a message, as produced by tools that used to produce QLDs. */ class DefectExternalData extends ExternalData { - DefectExternalData() { - this.getField(0).regexpMatch("\\w+://.*:[0-9]+:[0-9]+:[0-9]+:[0-9]+$") and - this.getNumFields() = 2 - } - - string getURL() { result = getField(0) } + DefectExternalData() { + this.getField(0).regexpMatch("\\w+://.*:[0-9]+:[0-9]+:[0-9]+:[0-9]+$") and + this.getNumFields() = 2 + } - string getMessage() { result = getField(1) } + string getURL() { result = getField(0) } + + string getMessage() { result = getField(1) } } - diff --git a/python/ql/src/external/Thrift.qll b/python/ql/src/external/Thrift.qll index a10d5aab506..658d3f301cd 100644 --- a/python/ql/src/external/Thrift.qll +++ b/python/ql/src/external/Thrift.qll @@ -3,68 +3,42 @@ * This code is under development and may change without warning. */ - import external.ExternalArtifact /** An item in the parse tree of the IDL file */ class ThriftElement extends ExternalData { - string kind; - ThriftElement() { - this.getDataPath() = "thrift-" + kind - } + ThriftElement() { this.getDataPath() = "thrift-" + kind } - string getKind() { - result = kind - } + string getKind() { result = kind } - string getId() { - result = getField(0) - } + string getId() { result = getField(0) } - int getIndex() { - result = getFieldAsInt(1) - } + int getIndex() { result = getFieldAsInt(1) } - ThriftElement getParent() { - result.getId() = this.getField(2) - } + ThriftElement getParent() { result.getId() = this.getField(2) } - string getValue() { - result = this.getField(3) - } + string getValue() { result = this.getField(3) } - ThriftElement getChild(int n) { - result.getIndex() = n and result.getParent() = this - } + ThriftElement getChild(int n) { result.getIndex() = n and result.getParent() = this } - ThriftElement getAChild() { - result = this.getChild(_) - } + ThriftElement getAChild() { result = this.getChild(_) } - override string toString() { - result = this.getKind() - } + override string toString() { result = this.getKind() } - string getPath() { - result = this.getField(4) - } + string getPath() { result = this.getField(4) } - private int line() { - result = this.getFieldAsInt(5) - } + private int line() { result = this.getFieldAsInt(5) } - private int column() { - result = this.getFieldAsInt(6) - } + private int column() { result = this.getFieldAsInt(6) } predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) { fp = this.getPath() and bl = this.line() and bc = this.column() and el = this.line() and - ec = this.column() + this.getValue().length()-1 + ec = this.column() + this.getValue().length() - 1 or exists(ThriftElement first, ThriftElement last | first = this.getChild(min(int l | exists(this.getChild(l)))) and @@ -74,19 +48,13 @@ class ThriftElement extends ExternalData { ) } - File getFile() { - this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) - } - + File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) } } abstract class ThriftNamedElement extends ThriftElement { - abstract ThriftElement getNameElement(); - final string getName() { - result = this.getNameElement().getValue() - } + final string getName() { result = this.getNameElement().getValue() } override string toString() { result = this.getKind() + " " + this.getName() @@ -101,14 +69,10 @@ abstract class ThriftNamedElement extends ThriftElement { this.getNameElement().hasLocationInfo(fp, _, _, el, ec) ) } - } class ThriftType extends ThriftNamedElement { - - ThriftType() { - kind.matches("%type") - } + ThriftType() { kind.matches("%type") } override ThriftElement getNameElement() { result = this.getChild(0) @@ -116,9 +80,7 @@ class ThriftType extends ThriftNamedElement { result = this.getChild(0).(ThriftType).getNameElement() } - override string toString() { - result = "type " + this.getName() - } + override string toString() { result = "type " + this.getName() } predicate references(ThriftStruct struct) { this.getName() = struct.getName() and @@ -127,194 +89,106 @@ class ThriftType extends ThriftNamedElement { struct.hasLocationInfo(path, _, _, _, _) ) } - } /** A thrift typedef */ class ThriftTypeDef extends ThriftNamedElement { + ThriftTypeDef() { kind.matches("typedef") } - ThriftTypeDef() { - kind.matches("typedef") - } - - override ThriftElement getNameElement() { - result = this.getChild(2).getChild(0) - } + override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) } } /** A thrift enum declaration */ class ThriftEnum extends ThriftNamedElement { + ThriftEnum() { kind.matches("enum") } - ThriftEnum() { - kind.matches("enum") - } - - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } } /** A thrift enum field */ class ThriftEnumField extends ThriftNamedElement { + ThriftEnumField() { kind.matches("enumfield") } - ThriftEnumField() { - kind.matches("enumfield") - } - - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } } /** A thrift service declaration */ class ThriftService extends ThriftNamedElement { + ThriftService() { kind.matches("service") } - ThriftService() { - kind.matches("service") - } + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - - ThriftFunction getAFunction() { - result = this.getChild(_) - } + ThriftFunction getAFunction() { result = this.getChild(_) } ThriftFunction getFunction(string name) { result.getName() = name and result = this.getAFunction() } - } /** A thrift function declaration */ class ThriftFunction extends ThriftNamedElement { + ThriftFunction() { kind.matches("function") } - ThriftFunction() { - kind.matches("function") - } + override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(2).getChild(0) - } + ThriftField getArgument(int n) { result = this.getChild(n + 3) } - ThriftField getArgument(int n) { - result = this.getChild(n+3) - } + ThriftField getAnArgument() { result = this.getArgument(_) } - ThriftField getAnArgument() { - result = this.getArgument(_) - } + private ThriftThrows getAllThrows() { result = this.getChild(_) } - private ThriftThrows getAllThrows() { - result = this.getChild(_) - } + ThriftField getAThrows() { result = this.getAllThrows().getAChild() } - ThriftField getAThrows() { - result = this.getAllThrows().getAChild() - } - - ThriftType getReturnType() { - result = this.getChild(1).getChild(0) - } + ThriftType getReturnType() { result = this.getChild(1).getChild(0) } override predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) { this.getChild(1).hasLocationInfo(fp, bl, bc, _, _) and this.getChild(2).hasLocationInfo(fp, _, _, el, ec) } - ThriftService getService() { - result.getAFunction() = this - } - - string getQualifiedName() { - result = this.getService().getName() + "." + this.getName() - } + ThriftService getService() { result.getAFunction() = this } + string getQualifiedName() { result = this.getService().getName() + "." + this.getName() } } class ThriftField extends ThriftNamedElement { + ThriftField() { kind.matches("field") } - ThriftField() { - kind.matches("field") - } - - override ThriftElement getNameElement() { - result = this.getChild(4) - } - - ThriftType getType() { - result = this.getChild(2) - } + override ThriftElement getNameElement() { result = this.getChild(4) } + ThriftType getType() { result = this.getChild(2) } } -class ThriftStruct extends ThriftNamedElement { +class ThriftStruct extends ThriftNamedElement { + ThriftStruct() { kind.matches("struct") } - ThriftStruct() { - kind.matches("struct") - } + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - - ThriftField getMember(int n) { - result = this.getChild(n+1) - } - - ThriftField getAMember() { - result = this.getMember(_) - } + ThriftField getMember(int n) { result = this.getChild(n + 1) } + ThriftField getAMember() { result = this.getMember(_) } } - class ThriftException extends ThriftNamedElement { + ThriftException() { kind.matches("exception") } - ThriftException() { - kind.matches("exception") - } + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - - ThriftField getMember(int n) { - result = this.getChild(n+1) - } - - ThriftField getAMember() { - result = this.getMember(_) - } + ThriftField getMember(int n) { result = this.getChild(n + 1) } + ThriftField getAMember() { result = this.getMember(_) } } - class ThriftThrows extends ThriftElement { + ThriftThrows() { kind.matches("throws") } - ThriftThrows() { - kind.matches("throws") - } - - ThriftField getAThrows() { - result = this.getChild(_) - } - + ThriftField getAThrows() { result = this.getChild(_) } } /** A parse tree element that holds a primitive value */ class ThriftValue extends ThriftElement { + ThriftValue() { exists(this.getValue()) } - ThriftValue() { - exists(this.getValue()) - } - - override string toString() { - result = this.getKind() + " " + this.getValue() - } - + override string toString() { result = this.getKind() + " " + this.getValue() } } diff --git a/python/ql/src/external/VCS.qll b/python/ql/src/external/VCS.qll index 6b665dde510..2d03f7d882d 100644 --- a/python/ql/src/external/VCS.qll +++ b/python/ql/src/external/VCS.qll @@ -1,92 +1,76 @@ import python class Commit extends @svnentry { + Commit() { + svnaffectedfiles(this, _, _) and + exists(date svnDate, date snapshotDate | + svnentries(this, _, _, svnDate, _) and + snapshotDate(snapshotDate) and + svnDate <= snapshotDate + ) + } - Commit() { - svnaffectedfiles(this, _, _) and - exists(date svnDate, date snapshotDate | - svnentries(this, _, _, svnDate, _) and - snapshotDate(snapshotDate) and - svnDate <= snapshotDate - ) - } + string toString() { result = this.getRevisionName() } - string toString() { result = this.getRevisionName() } + string getRevisionName() { svnentries(this, result, _, _, _) } - string getRevisionName() { svnentries(this, result, _, _, _) } - - string getAuthor() { svnentries(this, _, result, _, _) } - - date getDate() { svnentries(this, _, _, result, _) } - - int getChangeSize() { svnentries(this, _, _, _, result) } - - string getMessage() { svnentrymsg(this, result) } - - string getAnAffectedFilePath(string action) { - exists(File rawFile | svnaffectedfiles(this, rawFile, action) | - result = rawFile.getName() - ) - } - - string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) } - - File getAnAffectedFile(string action) { - svnaffectedfiles(this,result,action) - } + string getAuthor() { svnentries(this, _, result, _, _) } - File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) } + date getDate() { svnentries(this, _, _, result, _) } - predicate isRecent() { recentCommit(this) } - - int daysToNow() { - exists(date now | snapshotDate(now) | - result = getDate().daysTo(now) and result >= 0 - ) - } - - int getRecentAdditionsForFile(File f) { - svnchurn(this, f, result, _) - } - - int getRecentDeletionsForFile(File f) { - svnchurn(this, f, _, result) - } + int getChangeSize() { svnentries(this, _, _, _, result) } - int getRecentChurnForFile(File f) { - result = getRecentAdditionsForFile(f) + getRecentDeletionsForFile(f) - } + string getMessage() { svnentrymsg(this, result) } + string getAnAffectedFilePath(string action) { + exists(File rawFile | svnaffectedfiles(this, rawFile, action) | result = rawFile.getName()) + } + + string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) } + + File getAnAffectedFile(string action) { svnaffectedfiles(this, result, action) } + + File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) } + + predicate isRecent() { recentCommit(this) } + + int daysToNow() { + exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0) + } + + int getRecentAdditionsForFile(File f) { svnchurn(this, f, result, _) } + + int getRecentDeletionsForFile(File f) { svnchurn(this, f, _, result) } + + int getRecentChurnForFile(File f) { + result = getRecentAdditionsForFile(f) + getRecentDeletionsForFile(f) + } } class Author extends string { - Author() { exists(Commit e | this = e.getAuthor()) } - - Commit getACommit() { result.getAuthor() = this } - - File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } - + Author() { exists(Commit e | this = e.getAuthor()) } + + Commit getACommit() { result.getAuthor() = this } + + File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } } predicate recentCommit(Commit e) { - exists(date snapshotDate, date commitDate, int days | - snapshotDate(snapshotDate) and - e.getDate() = commitDate and - days = commitDate.daysTo(snapshotDate) and - days >= 0 and days <= 60 - ) + exists(date snapshotDate, date commitDate, int days | + snapshotDate(snapshotDate) and + e.getDate() = commitDate and + days = commitDate.daysTo(snapshotDate) and + days >= 0 and + days <= 60 + ) } date firstChange(File f) { - result = min(Commit e, date toMin | (f = e.getAnAffectedFile()) and (toMin = e.getDate()) | toMin) + result = min(Commit e, date toMin | f = e.getAnAffectedFile() and toMin = e.getDate() | toMin) } predicate firstCommit(Commit e) { - not exists(File f | f = e.getAnAffectedFile() | - firstChange(f) < e.getDate() - ) + not exists(File f | f = e.getAnAffectedFile() | firstChange(f) < e.getDate()) } -predicate artificialChange(Commit e) { - firstCommit(e) or e.getChangeSize() >= 50000 -} \ No newline at end of file +predicate artificialChange(Commit e) { firstCommit(e) or e.getChangeSize() >= 50000 } diff --git a/python/ql/src/python.qll b/python/ql/src/python.qll index d1c096ff4ac..6cf0802d993 100644 --- a/python/ql/src/python.qll +++ b/python/ql/src/python.qll @@ -34,5 +34,4 @@ import semmle.python.pointsto.Base import semmle.python.pointsto.Context import semmle.python.pointsto.CallGraph import semmle.python.objects.ObjectAPI - import site diff --git a/python/ql/src/semmle/crypto/Crypto.qll b/python/ql/src/semmle/crypto/Crypto.qll index 12e81a393ce..4eaa3eb8dbd 100644 --- a/python/ql/src/semmle/crypto/Crypto.qll +++ b/python/ql/src/semmle/crypto/Crypto.qll @@ -2,10 +2,10 @@ * Provides classes for modeling cryptographic libraries. */ -/* The following information is copied from `/semmlecode-javascript-queries/semmle/javascript/frameworks/CryptoLibraries.qll` +/* + * The following information is copied from `/semmlecode-javascript-queries/semmle/javascript/frameworks/CryptoLibraries.qll` * which should be considered the definitive version (as of Feb 2018) */ - /** * Names of cryptographic algorithms, separated into strong and weak variants. @@ -13,15 +13,17 @@ * The names are normalized: upper-case, no spaces, dashes or underscores. * * The names are inspired by the names used in real world crypto libraries. - * */ private module AlgorithmNames { predicate isStrongHashingAlgorithm(string name) { name = "DSA" or name = "ED25519" or - name = "ES256" or name = "ECDSA256" or - name = "ES384" or name = "ECDSA384" or - name = "ES512" or name = "ECDSA512" or + name = "ES256" or + name = "ECDSA256" or + name = "ES384" or + name = "ECDSA384" or + name = "ES512" or + name = "ECDSA512" or name = "SHA2" or name = "SHA224" or name = "SHA256" or @@ -54,15 +56,21 @@ private module AlgorithmNames { name = "RSA" or name = "RABBIT" or name = "BLOWFISH" - } predicate isWeakEncryptionAlgorithm(string name) { name = "DES" or - name = "3DES" or name = "TRIPLEDES" or name = "TDEA" or name = "TRIPLEDEA" or - name = "ARC2" or name = "RC2" or - name = "ARC4" or name = "RC4" or name = "ARCFOUR" or - name = "ARC5" or name = "RC5" + name = "3DES" or + name = "TRIPLEDES" or + name = "TDEA" or + name = "TRIPLEDEA" or + name = "ARC2" or + name = "RC2" or + name = "ARC4" or + name = "RC4" or + name = "ARCFOUR" or + name = "ARC5" or + name = "RC5" } predicate isStrongPasswordHashingAlgorithm(string name) { @@ -72,51 +80,45 @@ private module AlgorithmNames { name = "SCRYPT" } - predicate isWeakPasswordHashingAlgorithm(string name) { - none() - } + predicate isWeakPasswordHashingAlgorithm(string name) { none() } /** * Normalizes `name`: upper-case, no spaces, dashes or underscores. * * All names of this module are in this normalized form. */ - bindingset[name] string normalizeName(string name) { - result = name.toUpperCase().regexpReplaceAll("[-_ ]", "") - } - + bindingset[name] + string normalizeName(string name) { result = name.toUpperCase().regexpReplaceAll("[-_ ]", "") } } -private import AlgorithmNames +private import AlgorithmNames /** * A cryptographic algorithm. */ private newtype TCryptographicAlgorithm = -MkHashingAlgorithm(string name, boolean isWeak) { - (isStrongHashingAlgorithm(name) and isWeak = false) or - (isWeakHashingAlgorithm(name) and isWeak = true) -} -or -MkEncryptionAlgorithm(string name, boolean isWeak) { - (isStrongEncryptionAlgorithm(name) and isWeak = false) or - (isWeakEncryptionAlgorithm(name) and isWeak = true) -} -or -MkPasswordHashingAlgorithm(string name, boolean isWeak) { - (isStrongPasswordHashingAlgorithm(name) and isWeak = false) or - (isWeakPasswordHashingAlgorithm(name) and isWeak = true) -} + MkHashingAlgorithm(string name, boolean isWeak) { + isStrongHashingAlgorithm(name) and isWeak = false + or + isWeakHashingAlgorithm(name) and isWeak = true + } or + MkEncryptionAlgorithm(string name, boolean isWeak) { + isStrongEncryptionAlgorithm(name) and isWeak = false + or + isWeakEncryptionAlgorithm(name) and isWeak = true + } or + MkPasswordHashingAlgorithm(string name, boolean isWeak) { + isStrongPasswordHashingAlgorithm(name) and isWeak = false + or + isWeakPasswordHashingAlgorithm(name) and isWeak = true + } /** * A cryptographic algorithm. */ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { - /** Gets a textual representation of this element. */ - string toString() { - result = getName() - } + string toString() { result = getName() } /** * Gets the name of the algorithm. @@ -127,76 +129,46 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { * Holds if this algorithm is weak. */ abstract predicate isWeak(); - } /** * A hashing algorithm such as `MD5` or `SHA512`. */ class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - HashingAlgorithm() { - this = MkHashingAlgorithm(name, isWeak) - } + HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } - override string getName() { - result = name - } - - override predicate isWeak() { - isWeak = true - } + override string getName() { result = name } + override predicate isWeak() { isWeak = true } } /** * An encryption algorithm such as `DES` or `AES512`. */ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - EncryptionAlgorithm() { - this = MkEncryptionAlgorithm(name, isWeak) - } + EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } - override string getName() { - result = name - } - - override predicate isWeak() { - isWeak = true - } + override string getName() { result = name } + override predicate isWeak() { isWeak = true } } /** * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. */ -class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { - +class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { string name; - boolean isWeak; - PasswordHashingAlgorithm() { - this = MkPasswordHashingAlgorithm(name, isWeak) - } + PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } - override string getName() { - result = name - } + override string getName() { result = name } - override predicate isWeak() { - isWeak = true - } + override predicate isWeak() { isWeak = true } } - - - diff --git a/python/ql/src/semmle/files/FileSystem.qll b/python/ql/src/semmle/files/FileSystem.qll index 4ec67c7c2e6..4e28b33d96d 100644 --- a/python/ql/src/semmle/files/FileSystem.qll +++ b/python/ql/src/semmle/files/FileSystem.qll @@ -1,2 +1,3 @@ /** Provides classes for working with files and folders. */ + import semmle.python.Files From bb2ce6e5d9f8341565195c526912f1ee3f2ff53d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 20 Mar 2020 16:23:15 +0000 Subject: [PATCH 118/459] C++: More missing override tags. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll index 998329a3e47..d44b28f041d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll @@ -62,13 +62,13 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid override predicate hasOnlySpecificWriteSideEffects() { any() } - predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { i = 0 and buffer = true and mustWrite = false } - predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { (i = 0 or i = 1) and buffer = true } From d529fedbadfea238191337a82ff14c08da53610a Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 20 Mar 2020 11:00:54 -0700 Subject: [PATCH 119/459] C++: accept extractor changes to IR --- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 16 ++++++++-------- .../ir/ssa/aliased_ssa_ir_unsound.expected | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 5e3a1d15455..00077ec850c 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6330,12 +6330,12 @@ ir.cpp: #-----| Goto -> Block 5 # 1235| Block 5 -# 1235| v1235_1(void) = NoOp : -# 1231| v1231_9(void) = ReturnIndirection : &:r1231_7, ~mu1231_4 -# 1231| v1231_10(void) = ReturnVoid : -# 1231| v1231_11(void) = UnmodeledUse : mu* -# 1231| v1231_12(void) = AliasedUse : ~mu1231_4 -# 1231| v1231_13(void) = ExitFunction : +# 1235| v1235_1(void) = NoOp : +# 1231| v1231_9(void) = ReturnIndirection[dynamic] : &:r1231_7, ~mu1231_4 +# 1231| v1231_10(void) = ReturnVoid : +# 1231| v1231_11(void) = UnmodeledUse : mu* +# 1231| v1231_12(void) = AliasedUse : ~mu1231_4 +# 1231| v1231_13(void) = ExitFunction : # 1232| Block 6 # 1232| r1232_4(glval) = VariableAddress[a] : @@ -6408,7 +6408,7 @@ struct_init.cpp: # 17| r17_3(glval) = VariableAddress[global_pointer] : # 17| mu17_4(Info *) = Store : &:r17_3, r17_2 # 18| v18_1(void) = NoOp : -# 16| v16_9(void) = ReturnIndirection : &:r16_7, ~mu16_4 +# 16| v16_9(void) = ReturnIndirection[info] : &:r16_7, ~mu16_4 # 16| v16_10(void) = ReturnVoid : # 16| v16_11(void) = UnmodeledUse : mu* # 16| v16_12(void) = AliasedUse : ~mu16_4 @@ -6498,7 +6498,7 @@ struct_init.cpp: # 41| v41_6(void) = ^BufferReadSideEffect[0] : &:r41_3, ~mu36_4 # 41| mu41_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r41_3 # 42| v42_1(void) = NoOp : -# 36| v36_9(void) = ReturnIndirection : &:r36_7, ~mu36_4 +# 36| v36_9(void) = ReturnIndirection[name1] : &:r36_7, ~mu36_4 # 36| v36_10(void) = ReturnVoid : # 36| v36_11(void) = UnmodeledUse : mu* # 36| v36_12(void) = AliasedUse : ~mu36_4 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index dc765b62097..6df7ff9737c 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1301,7 +1301,7 @@ ssa.cpp: # 277| m277_8(unknown) = Chi : total:m276_4, partial:m277_7 # 277| v277_9(void) = ^BufferReadSideEffect[1] : &:r277_5, ~m276_11 # 277| m277_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r277_5 -# 277| m277_11(char *) = Chi : total:m276_11, partial:m277_10 +# 277| m277_11(unknown) = Chi : total:m276_11, partial:m277_10 # 278| r278_1(glval) = FunctionAddress[unknownFunction] : # 278| r278_2(glval) = VariableAddress[argc] : # 278| r278_3(int) = Load : &:r278_2, m276_7 @@ -1312,7 +1312,7 @@ ssa.cpp: # 278| m278_8(unknown) = Chi : total:m277_8, partial:m278_7 # 278| v278_9(void) = ^BufferReadSideEffect[1] : &:r278_5, ~m277_11 # 278| m278_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r278_5 -# 278| m278_11(char *) = Chi : total:m277_11, partial:m278_10 +# 278| m278_11(unknown) = Chi : total:m277_11, partial:m278_10 # 279| r279_1(glval) = VariableAddress[#return] : # 279| r279_2(glval) = VariableAddress[argv] : # 279| r279_3(char **) = Load : &:r279_2, m276_9 From f29f0f418f26422b363e489ec4e4b988e48f9ec3 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 13 Mar 2020 16:58:30 +0100 Subject: [PATCH 120/459] Dataflow: Exclude flow param-param flow through with identical params. --- .../semmle/code/cpp/dataflow/internal/DataFlowImpl.qll | 8 ++++++-- .../semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll | 8 ++++++-- .../semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll | 8 ++++++-- .../semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll | 8 ++++++-- .../code/cpp/dataflow/internal/DataFlowImplLocal.qll | 8 ++++++-- .../semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll | 8 ++++++-- .../code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 8 ++++++-- .../code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 8 ++++++-- .../code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 8 ++++++-- .../semmle/code/csharp/dataflow/internal/DataFlowImpl.qll | 8 ++++++-- .../code/csharp/dataflow/internal/DataFlowImpl2.qll | 8 ++++++-- .../code/csharp/dataflow/internal/DataFlowImpl3.qll | 8 ++++++-- .../code/csharp/dataflow/internal/DataFlowImpl4.qll | 8 ++++++-- .../code/csharp/dataflow/internal/DataFlowImpl5.qll | 8 ++++++-- .../semmle/code/java/dataflow/internal/DataFlowImpl.qll | 8 ++++++-- .../semmle/code/java/dataflow/internal/DataFlowImpl2.qll | 8 ++++++-- .../semmle/code/java/dataflow/internal/DataFlowImpl3.qll | 8 ++++++-- .../semmle/code/java/dataflow/internal/DataFlowImpl4.qll | 8 ++++++-- .../semmle/code/java/dataflow/internal/DataFlowImpl5.qll | 8 ++++++-- 19 files changed, 114 insertions(+), 38 deletions(-) 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 f7f9b2a0393..4ff12c4e882 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 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 @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 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 @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 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 @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 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 @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } 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 f7f9b2a0393..4ff12c4e882 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -2088,6 +2088,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2481,13 +2483,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } From 22381f3ee616729836f79f60cf938a8a546b181e Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 24 Mar 2020 22:01:56 +0100 Subject: [PATCH 121/459] C++: Demonstrate amount of field flow already present --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 1 + .../dataflow/fields/ir-flow.expected | 31 +++++++++++++ .../library-tests/dataflow/fields/ir-flow.ql | 46 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected create mode 100644 cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index e19912a63ee..c89d7312813 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -63,6 +63,7 @@ class Node extends TIRDataFlowNode { */ Variable asVariable() { result = this.(VariableNode).getVariable() } + /** * DEPRECATED: See UninitializedNode. * diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected new file mode 100644 index 00000000000..2503be80b00 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -0,0 +1,31 @@ +edges +| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | +| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | +nodes +| aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | +| aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | +| aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | +| aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | +| aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | +| struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void | +| struct_init.c:22:11:22:11 | a | semmle.label | a | +| struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void | +| struct_init.c:31:23:31:23 | a | semmle.label | a | +#select +| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void | +| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input : void | call to user_input : void | +| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input : void | call to user_input : void | +| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input : void | call to user_input : void | +| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input : void | call to user_input : void | +| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input : void | call to user_input : void | +| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input : void | call to user_input : void | diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql new file mode 100644 index 00000000000..098c6b6bd27 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql @@ -0,0 +1,46 @@ +/** + * @kind path-problem + */ + +import semmle.code.cpp.ir.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate +import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon +import semmle.code.cpp.ir.IR +import DataFlow::PathGraph +import cpp + +class Conf extends DataFlow::Configuration { + Conf() { this = "FieldFlowConf" } + + override predicate isSource(Node src) { + src.asExpr() instanceof NewExpr + or + src.asExpr().(Call).getTarget().hasName("user_input") + or + exists(FunctionCall fc | + fc.getAnArgument() = src.asDefiningArgument() and + fc.getTarget().hasName("argument_source") + ) + } + + override predicate isSink(Node sink) { + exists(Call c | + c.getTarget().hasName("sink") and + c.getAnArgument() = sink.asExpr() + ) + } + + override predicate isAdditionalFlowStep(Node a, Node b) { + b.asPartialDefinition() = + any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr()) + .getQualifier() + or + b.asExpr().(AddressOfExpr).getOperand() = a.asExpr() + } +} + +from DataFlow::PathNode src, DataFlow::PathNode sink, Conf conf +where conf.hasFlowPath(src, sink) +select sink, src, sink, sink + " flows from $@", src, src.toString() From a5f08e1ea6c746e3340850c2b82617cf27f581b8 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 24 Mar 2020 22:07:50 +0100 Subject: [PATCH 122/459] C++: Split parameter node class into an explicit and implicit version --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index c89d7312813..9373483051e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -55,7 +55,7 @@ class Node extends TIRDataFlowNode { Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() } /** Gets the parameter corresponding to this node, if any. */ - Parameter asParameter() { result = this.(ParameterNode).getParameter() } + Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() } /** * Gets the variable corresponding to this node, if any. This can be used for @@ -143,27 +143,37 @@ class ExprNode extends InstructionNode { override string toString() { result = this.asConvertedExpr().toString() } } -/** - * The value of a parameter at function entry, viewed as a node in a data - * flow graph. - */ class ParameterNode extends InstructionNode { - override InitializeParameterInstruction instr; - /** * Holds if this node is the parameter of `c` at the specified (zero-based) * position. The implicit `this` parameter is considered to have index `-1`. */ - predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() } + predicate isParameterOf(Function f, int i) { + none() + } +} + +/** + * The value of a parameter at function entry, viewed as a node in a data + * flow graph. + */ +private class ExplicitParameterNode extends ParameterNode { + override InitializeParameterInstruction instr; + + override predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() } Parameter getParameter() { result = instr.getParameter() } override string toString() { result = instr.getParameter().toString() } } -private class ThisParameterNode extends InstructionNode { +private class ThisParameterNode extends ParameterNode { override InitializeThisInstruction instr; + override predicate isParameterOf(Function f, int i) { + i = -1 and instr.getEnclosingFunction() = f + } + override string toString() { result = "this" } } @@ -295,7 +305,7 @@ ExprNode convertedExprNode(Expr e) { result.getExpr() = e } /** * Gets the `Node` corresponding to the value of `p` at function entry. */ -ParameterNode parameterNode(Parameter p) { result.getParameter() = p } +ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p } /** Gets the `VariableNode` corresponding to the variable `v`. */ VariableNode variableNode(Variable v) { result.getVariable() = v } From 077c282cd3e5dc2d9838d92d178f5f16a32a87bc Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 24 Mar 2020 22:11:29 +0100 Subject: [PATCH 123/459] C++: Add field flow and accept tests --- .../ir/dataflow/internal/DataFlowPrivate.qll | 16 ++++- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 67 +++++++++++++++---- .../dataflow/fields/ir-flow.expected | 60 +++++++++++++++++ 3 files changed, 128 insertions(+), 15 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 83e5d5eb06b..861a09f144a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -131,7 +131,14 @@ private class ArrayContent extends Content, TArrayContent { * value of `node1`. */ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { - none() // stub implementation + exists(FieldAddressInstruction fa | + exists(StoreInstruction store | + node1.asInstruction() = store and + store.getDestinationAddress() = fa + ) and + node2.getPreUpdateNode().asInstruction() = fa.getObjectAddress() and + f.(FieldContent).getField() = fa.getField() + ) } /** @@ -140,7 +147,12 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { * `node2`. */ predicate readStep(Node node1, Content f, Node node2) { - none() // stub implementation + exists(FieldAddressInstruction fa, LoadInstruction load | + load.getSourceAddress() = fa and + node1.asInstruction() = fa.getObjectAddress() and + fa.getField() = f.(FieldContent).getField() and + load = node2.asInstruction() + ) } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 9373483051e..2b88cc7ade1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -63,6 +63,9 @@ class Node extends TIRDataFlowNode { */ Variable asVariable() { result = this.(VariableNode).getVariable() } + Expr asPartialDefinition() { + result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression() + } /** * DEPRECATED: See UninitializedNode. @@ -213,6 +216,19 @@ abstract class PostUpdateNode extends InstructionNode { * Gets the node before the state update. */ abstract Node getPreUpdateNode(); + + override string toString() { result = getPreUpdateNode().toString() + " [post update]" } +} + +abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { } + +class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { + override StoreInstruction instr; + FieldAddressInstruction field; + + ExplicitFieldStoreQualifierNode() { field = instr.getDestinationAddress() } + + override Node getPreUpdateNode() { result.asInstruction() = field.getObjectAddress() } } /** @@ -225,24 +241,24 @@ abstract class PostUpdateNode extends InstructionNode { * returned. This node will have its `getArgument()` equal to `&x` and its * `getVariableAccess()` equal to `x`. */ -class DefinitionByReferenceNode extends InstructionNode { +class DefinitionByReferenceNode extends PartialDefinitionNode { override WriteSideEffectInstruction instr; + CallInstruction call; + + DefinitionByReferenceNode() { call = instr.getPrimaryInstruction() } + + override Node getPreUpdateNode() { + result.asInstruction() = call.getPositionalArgument(instr.getIndex()) + or + result.asInstruction() = call.getThisArgument() and + instr.getIndex() = -1 + } /** Gets the argument corresponding to this node. */ Expr getArgument() { - result = - instr - .getPrimaryInstruction() - .(CallInstruction) - .getPositionalArgument(instr.getIndex()) - .getUnconvertedResultExpression() + result = call.getPositionalArgument(instr.getIndex()).getUnconvertedResultExpression() or - result = - instr - .getPrimaryInstruction() - .(CallInstruction) - .getThisArgument() - .getUnconvertedResultExpression() and + result = call.getThisArgument().getUnconvertedResultExpression() and instr.getIndex() = -1 } @@ -250,6 +266,24 @@ class DefinitionByReferenceNode extends InstructionNode { Parameter getParameter() { exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex())) } + + override string toString() { result = "ref arg " + getPreUpdateNode().toString() } +} + +class PositionalArgumentWithoutWriteSideEffectNode extends PartialDefinitionNode { + override CallInstruction instr; + PositionalArgumentOperand op; + + PositionalArgumentWithoutWriteSideEffectNode() { + instr.getAnOperand() = op and + not exists(WriteSideEffectInstruction write | + write.getIndex() = op.getIndex() and write.getPrimaryInstruction() = instr + ) + } + + override Node getPreUpdateNode() { result.asInstruction() = op.getDef() } + + override string toString() { result = "no change to " + op.toString() } } /** @@ -332,6 +366,13 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr */ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) + or + exists(ChiInstruction chi, LoadInstruction load | + chi.getPartial() = nodeFrom.(PartialDefinitionNode).getInstruction() and + // TODO: This can probably be getSourceValue() after #3112 is merged + load.getSourceValueOperand().getAnyDef() = chi and + nodeTo.asInstruction() = load.getSourceAddress().(FieldAddressInstruction).getObjectAddress() + ) } private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) { diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index 2503be80b00..c66255c7338 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -1,27 +1,87 @@ edges +| A.cpp:126:5:126:5 | ref arg b [c] : void | A.cpp:131:8:131:8 | ref arg b [c] : void | +| A.cpp:126:12:126:18 | new : void | A.cpp:126:5:126:5 | ref arg b [c] : void | +| A.cpp:131:8:131:8 | ref arg b [c] : void | A.cpp:132:10:132:10 | b [c] : void | +| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c | +| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c : void | +| A.cpp:132:13:132:13 | c : void | A.cpp:132:10:132:13 | (void *)... | +| aliasing.cpp:9:3:9:22 | s [post update] : void | aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | +| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | +| aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:9:3:9:22 | s [post update] : void | +| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | +| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | +| aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | +| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | aliasing.cpp:29:8:29:9 | s1 [m1] : void | +| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | aliasing.cpp:30:8:30:9 | s2 [m1] : void | +| aliasing.cpp:29:8:29:9 | s1 [m1] : void | aliasing.cpp:29:11:29:12 | m1 | +| aliasing.cpp:30:8:30:9 | s2 [m1] : void | aliasing.cpp:30:11:30:12 | m1 | +| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | s2 [post update] : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | s [post update] : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:93:12:93:13 | m1 | +| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | s [post update] : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | +| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | VariableAddress [post update] : void | | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:31:23:31:23 | a | +| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | FieldAddress [post update] : void | | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | nodes +| A.cpp:126:5:126:5 | ref arg b [c] : void | semmle.label | ref arg b [c] : void | +| A.cpp:126:12:126:18 | new : void | semmle.label | new : void | +| A.cpp:131:8:131:8 | ref arg b [c] : void | semmle.label | ref arg b [c] : void | +| A.cpp:132:10:132:10 | b [c] : void | semmle.label | b [c] : void | +| A.cpp:132:10:132:13 | (void *)... | semmle.label | (void *)... | +| A.cpp:132:13:132:13 | c | semmle.label | c | +| A.cpp:132:13:132:13 | c : void | semmle.label | c : void | +| aliasing.cpp:9:3:9:22 | s [post update] : void | semmle.label | s [post update] : void | +| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void | +| aliasing.cpp:9:11:9:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | +| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void | +| aliasing.cpp:13:10:13:19 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | semmle.label | ref arg & ... [m1] : void | +| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | semmle.label | ref arg (reference to) [m1] : void | +| aliasing.cpp:29:8:29:9 | s1 [m1] : void | semmle.label | s1 [m1] : void | +| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 | +| aliasing.cpp:30:8:30:9 | s2 [m1] : void | semmle.label | s2 [m1] : void | +| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | +| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | +| aliasing.cpp:42:3:42:22 | s2 [post update] : void | semmle.label | s2 [post update] : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | +| aliasing.cpp:79:3:79:22 | s [post update] : void | semmle.label | s [post update] : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | +| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | +| aliasing.cpp:92:3:92:23 | s [post update] : void | semmle.label | s [post update] : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | +| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | semmle.label | VariableAddress [post update] : void | | struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void | | struct_init.c:22:11:22:11 | a | semmle.label | a | +| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | semmle.label | FieldAddress [post update] : void | | struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void | | struct_init.c:31:23:31:23 | a | semmle.label | a | #select +| A.cpp:132:10:132:13 | (void *)... | A.cpp:126:12:126:18 | new : void | A.cpp:132:10:132:13 | (void *)... | (void *)... flows from $@ | A.cpp:126:12:126:18 | new : void | new : void | +| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new : void | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new : void | new : void | +| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input : void | call to user_input : void | +| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input : void | call to user_input : void | | aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void | | aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input : void | call to user_input : void | | aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input : void | call to user_input : void | From f92dd3c5654d7a17be7418993d59ac0a938344c5 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 24 Mar 2020 22:24:48 +0100 Subject: [PATCH 124/459] C++: Autoformat --- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 2b88cc7ade1..93aa394d599 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -151,9 +151,7 @@ class ParameterNode extends InstructionNode { * Holds if this node is the parameter of `c` at the specified (zero-based) * position. The implicit `this` parameter is considered to have index `-1`. */ - predicate isParameterOf(Function f, int i) { - none() - } + predicate isParameterOf(Function f, int i) { none() } } /** From 1d8e103322850522dd7beba8a9d802a560f8fbac Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Mar 2020 00:19:23 +0100 Subject: [PATCH 125/459] autoformat --- .../src/semmle/javascript/dataflow/Configuration.qll | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index eb0128c4f3a..2024ebf2511 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -268,7 +268,9 @@ abstract class Configuration extends string { * * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. */ - predicate isAdditionalLoadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + predicate isAdditionalLoadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { none() } } @@ -564,7 +566,9 @@ abstract class AdditionalFlowStep extends DataFlow::Node { * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. */ cached - predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + predicate loadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { loadProp = storeProp and loadStoreStep(pred, succ, loadProp) } @@ -930,7 +934,8 @@ private predicate isAdditionalStoreStep( * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. */ private predicate isAdditionalLoadStoreStep( - DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp, DataFlow::Configuration cfg + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp, + DataFlow::Configuration cfg ) { any(AdditionalFlowStep s).loadStoreStep(pred, succ, loadProp, storeProp) or From 12c6997e7bc1289072ba651eaf5c4674f82d8675 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 25 Mar 2020 11:55:29 +0100 Subject: [PATCH 126/459] Python: Reduce result set in custom taint sanitizer --- .../examples/custom-sanitizer/Taint.qll | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll index 072737be2cd..5cd4a007877 100644 --- a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll +++ b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll @@ -36,22 +36,34 @@ class MySanitizerHandlingNot extends Sanitizer { /** The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. */ override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { taint instanceof ExternalStringKind and - exists(CallNode call | - clears_taint_on_true(call, test.getTest(), test.getSense()) - | - call = Value::named("test.is_safe").getACall() and - test.getInput().getAUse() = call.getAnArg() - ) + clears_taint_on_true(_, test.getTest(), test.getSense(), test) } - private predicate clears_taint_on_true(ControlFlowNode final_test, ControlFlowNode test, boolean sense) { - final_test = test and - sense = true - or - test.(UnaryExprNode).getNode().getOp() instanceof Not and - exists(ControlFlowNode nested_test | - nested_test = test.(UnaryExprNode).getOperand() and - clears_taint_on_true(final_test, nested_test, sense.booleanNot()) + /** + * Helper predicate that recurses into any nesting of `not` + * + * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and + * ensure that `test` is a part of this `PyEdgeRefinement`. Without including `PyEdgeRefinement` as an argument + * *any* `CallNode c` to `test.is_safe` would be a result of this predicate, since (c, c, true) would hold. + */ + private predicate clears_taint_on_true( + CallNode final_test, ControlFlowNode test, boolean sense, PyEdgeRefinement edge_refinement + ) { + ( + edge_refinement.getTest().getNode().(Expr).getASubExpression*() = test.getNode() and + test.getNode().(Expr).getASubExpression*() = final_test.getNode() + ) and + ( + final_test = test and + final_test = Value::named("test.is_safe").getACall() and + edge_refinement.getInput().getAUse() = final_test.getAnArg() and + sense = true + or + test.(UnaryExprNode).getNode().getOp() instanceof Not and + exists(ControlFlowNode nested_test | + nested_test = test.(UnaryExprNode).getOperand() and + clears_taint_on_true(final_test, nested_test, sense.booleanNot(), edge_refinement) + ) ) } } From dc9dbf3682d040c40b97e9c62c40e08cb6b6ecc1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 25 Mar 2020 11:56:18 +0100 Subject: [PATCH 127/459] Python: Autoformat --- .../examples/custom-sanitizer/Taint.qll | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll index 5cd4a007877..15a2097eb26 100644 --- a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll +++ b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll @@ -17,13 +17,10 @@ class MySimpleSanitizer extends Sanitizer { * The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. * * Can't handle `if not is_safe(arg):` :\ that's why it's called MySimpleSanitizer - * */ override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { taint instanceof ExternalStringKind and - exists(CallNode call | - test.getTest() = call and test.getSense() = true - | + exists(CallNode call | test.getTest() = call and test.getSense() = true | call = Value::named("test.is_safe").getACall() and test.getInput().getAUse() = call.getAnArg() ) @@ -75,11 +72,7 @@ class TestConfig extends TaintTracking::Configuration { sanitizer instanceof MySanitizerHandlingNot } - override predicate isSource(TaintTracking::Source source) { - source instanceof SimpleSource - } + override predicate isSource(TaintTracking::Source source) { source instanceof SimpleSource } - override predicate isSink(TaintTracking::Sink sink) { - none() - } + override predicate isSink(TaintTracking::Sink sink) { none() } } From 6c9e35c22e41f3ec08ed51843d32d9780af67f98 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Mar 2020 12:45:37 +0000 Subject: [PATCH 128/459] JS: Skip .js files with a same-named .ts file next to it --- .../com/semmle/js/extractor/AutoBuild.java | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 35295ae0678..b3afccf2e07 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -565,17 +565,40 @@ public class AutoBuild { extractTypeScript( defaultExtractor, filesToExtract, tsconfigFiles, dependencyInstallationResult); + boolean hasTypeScriptFiles = extractedFiles.size() > 0; + // extract remaining files for (Path f : filesToExtract) { - if (extractedFiles.add(f)) { - FileExtractor extractor = defaultExtractor; - if (!fileTypes.isEmpty()) { - String extension = FileUtil.extension(f); - if (customExtractors.containsKey(extension)) extractor = customExtractors.get(extension); - } - extract(extractor, f, null); + if (extractedFiles.contains(f)) + continue; + if (hasTypeScriptFiles && isFileDerivedFromTypeScriptFile(f, extractedFiles)) { + continue; + } + extractedFiles.add(f); + FileExtractor extractor = defaultExtractor; + if (!fileTypes.isEmpty()) { + String extension = FileUtil.extension(f); + if (customExtractors.containsKey(extension)) extractor = customExtractors.get(extension); + } + extract(extractor, f, null); + } + } + + /** + * Returns true if the given path is likely the output of compiling a TypeScript file + * which we have already extracted. + */ + private boolean isFileDerivedFromTypeScriptFile(Path path, Set extractedFiles) { + String name = path.getFileName().toString(); + if (!name.endsWith(".js")) + return false; + String stem = name.substring(0, name.length() - ".js".length()); + for (String ext : FileType.TYPESCRIPT.getExtensions()) { + if (extractedFiles.contains(path.getParent().resolve(stem + ext))) { + return true; } } + return false; } /** Returns true if yarn is installed, otherwise prints a warning and returns false. */ From a78f1b864b86a1e0e15e4e51754f53b9b12f5aab Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Mar 2020 12:45:48 +0000 Subject: [PATCH 129/459] JS: Fix trailing whitespace --- .../src/com/semmle/js/extractor/AutoBuild.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index b3afccf2e07..36f831720f4 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -636,7 +636,7 @@ public class AutoBuild { } return null; } - + /** * Returns an existing file named dir/stem.ext where ext is any TypeScript or JavaScript extension, * or null if no such file exists. @@ -646,7 +646,7 @@ public class AutoBuild { if (resolved != null) return resolved; return tryResolveWithExtensions(dir, stem, FileType.JS.getExtensions()); } - + /** * Gets a child of a JSON object as a string, or null. */ @@ -681,7 +681,7 @@ public class AutoBuild { if (!verifyYarnInstallation()) { return DependencyInstallationResult.empty; } - + final Path sourceRoot = Paths.get(".").toAbsolutePath(); final Path virtualSourceRoot = Paths.get(EnvironmentVariables.getScratchDir()).toAbsolutePath(); @@ -769,7 +769,7 @@ public class AutoBuild { for (Path file : packageJsonFiles.keySet()) { Path relativePath = sourceRoot.relativize(file); Path virtualFile = virtualSourceRoot.resolve(relativePath); - + try { Files.createDirectories(virtualFile.getParent()); try (Writer writer = Files.newBufferedWriter(virtualFile)) { @@ -817,7 +817,7 @@ public class AutoBuild { */ private Path guessPackageMainFile(Path packageJsonFile, JsonObject packageJson, Iterable extensions) { Path packageDir = packageJsonFile.getParent(); - + // Try /index.ts. Path resolved = tryResolveWithExtensions(packageDir, "index", extensions); if (resolved != null) { From 54021a1c306b1db9afa0085919cd034b62777e5b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Mar 2020 13:24:18 +0000 Subject: [PATCH 130/459] JS: Update old entry point and add a test --- .../src/com/semmle/js/extractor/Main.java | 37 +++++++++++++++---- .../TypeScript/CompiledOutput/index.js | 1 + .../TypeScript/CompiledOutput/index.ts | 1 + .../TypeScript/CompiledOutput/test.expected | 1 + .../TypeScript/CompiledOutput/test.ql | 3 ++ 5 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.js create mode 100644 javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.ts create mode 100644 javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.expected create mode 100644 javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.ql diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 81e25eb23e0..56f4dc30fa2 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -1,5 +1,13 @@ package com.semmle.js.extractor; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + import com.semmle.js.extractor.ExtractorConfig.HTMLHandling; import com.semmle.js.extractor.ExtractorConfig.Platform; import com.semmle.js.extractor.ExtractorConfig.SourceType; @@ -23,13 +31,6 @@ import com.semmle.util.language.LegacyLanguage; import com.semmle.util.process.ArgsParser; import com.semmle.util.process.ArgsParser.FileMode; import com.semmle.util.trap.TrapWriter; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Pattern; /** The main entry point of the JavaScript extractor. */ public class Main { @@ -134,7 +135,8 @@ public class Main { TypeScriptParser tsParser = extractorState.getTypeScriptParser(); tsParser.setTypescriptRam(extractorConfig.getTypeScriptRam()); - if (containsTypeScriptFiles()) { + boolean containsTypeScriptFiles = containsTypeScriptFiles(); + if (containsTypeScriptFiles) { tsParser.verifyInstallation(!ap.has(P_QUIET)); } for (File projectFile : projectFiles) { @@ -190,10 +192,29 @@ public class Main { // Extract files that were not part of a project. for (File f : files) { + if (isFileDerivedFromTypeScriptFile(f)) + continue; ensureFileIsExtracted(f, ap); } } + /** + * Returns true if the given path is likely the output of compiling a TypeScript file + * which we have already extracted. + */ + private boolean isFileDerivedFromTypeScriptFile(File path) { + String name = path.getName(); + if (!name.endsWith(".js")) + return false; + String stem = name.substring(0, name.length() - ".js".length()); + for (String ext : FileType.TYPESCRIPT.getExtensions()) { + if (new File(path.getParent(), stem + ext).exists()) { + return true; + } + } + return false; + } + private void extractTypeTable(File fileHandle, TypeTable table) { TrapWriter trapWriter = extractorOutputConfig diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.js b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.js new file mode 100644 index 00000000000..80f511a99af --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.js @@ -0,0 +1 @@ +export default 45; diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.ts b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.ts new file mode 100644 index 00000000000..66ea6d25d40 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.ts @@ -0,0 +1 @@ +export default 45 as number; diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.expected b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.expected new file mode 100644 index 00000000000..5cd97cf9527 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.expected @@ -0,0 +1 @@ +| index.ts:0:0:0:0 | index.ts | diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.ql b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.ql new file mode 100644 index 00000000000..ff70967ddac --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.ql @@ -0,0 +1,3 @@ +import javascript + +query File files() { any() } From 7ac25d243907d257069d4b624d161d27adaff0a0 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 25 Mar 2020 13:22:05 +0100 Subject: [PATCH 131/459] C#: Add more tests for `cs/information-exposure-through-exception` --- .../CWE-209/ExceptionInformationExposure.cs | 8 +++++++ .../ExceptionInformationExposure.expected | 22 +++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs index 2a7cc3ae232..7de4fd18c75 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs @@ -2,10 +2,13 @@ using System; using System.Web; +using System.Web.UI.WebControls; public class StackTraceHandler : IHttpHandler { bool b; + TextBox textBox; + public void ProcessRequest(HttpContext ctx) { try @@ -34,6 +37,11 @@ public class StackTraceHandler : IHttpHandler // GOOD: log the stack trace, and send back a non-revealing response log("Exception occurred", ex); ctx.Response.Write("Exception occurred"); + + textBox.Text = ex.InnerException.StackTrace; // BAD (false negative) + textBox.Text = ex.StackTrace; // BAD (false negative) + textBox.Text = ex.ToString(); // BAD (false negative) + textBox.Text = ex.Message; // GOOD return; } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected index 3cdd0f50449..34c64432966 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected @@ -1,14 +1,14 @@ edges -| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | +| ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | nodes -| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | semmle.label | access to local variable ex : Exception | -| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | semmle.label | call to method ToString | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | semmle.label | access to local variable ex | -| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | semmle.label | access to property StackTrace | -| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | semmle.label | call to method ToString | +| ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | semmle.label | access to local variable ex : Exception | +| ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | semmle.label | call to method ToString | +| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | semmle.label | access to local variable ex | +| ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | semmle.label | access to property StackTrace | +| ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | semmle.label | call to method ToString | #select -| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | call to method ToString | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | access to local variable ex : Exception | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | access to local variable ex | -| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | access to property StackTrace | -| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | call to method ToString | +| ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | call to method ToString | +| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex | access to local variable ex : Exception | +| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | access to local variable ex | +| ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | call to method ToString | From ad1e0ec50b8efa3021790a998b6750638c4c05d5 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Mar 2020 14:01:33 +0000 Subject: [PATCH 132/459] JS: Inline variable again --- javascript/extractor/src/com/semmle/js/extractor/Main.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 56f4dc30fa2..4e9122fa053 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -135,8 +135,7 @@ public class Main { TypeScriptParser tsParser = extractorState.getTypeScriptParser(); tsParser.setTypescriptRam(extractorConfig.getTypeScriptRam()); - boolean containsTypeScriptFiles = containsTypeScriptFiles(); - if (containsTypeScriptFiles) { + if (containsTypeScriptFiles()) { tsParser.verifyInstallation(!ap.has(P_QUIET)); } for (File projectFile : projectFiles) { From 87970337aefb96ec910714c0196ac3bed7bab1e8 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Tue, 7 Jan 2020 18:21:23 +0000 Subject: [PATCH 133/459] C#: Improvements to buildless extraction, particularly for .NET Core. --- .gitignore | 3 +- .../AssemblyCache.cs | 14 +- .../BuildAnalysis.cs | 182 +++++---- .../CsProjFile.cs | 113 ++++++ .../DotNet.cs | 48 +++ .../DotNetRuntimeInfo.cs | 132 +++++++ .../MSBuildHelper.cs | 260 +++++++++++++ .../NugetPackageRepository.cs | 357 ++++++++++++++++++ .../NugetPackages.cs | 63 +--- .../Program.cs | 17 +- .../ProgressMonitor.cs | 43 ++- ...Semmle.Extraction.CSharp.Standalone.csproj | 7 +- .../SolutionFile.cs | 5 +- .../Entities/Expressions/Access.cs | 5 +- .../Entities/Expressions/MemberAccess.cs | 4 +- .../Entities/Types/NamedType.cs | 2 +- .../Entities/UsingDirective.cs | 2 +- csharp/extractor/Semmle.Extraction/Context.cs | 4 +- .../Semmle.Extraction/ExtractionScope.cs | 6 + .../extractor/Semmle.Extraction/Extractor.cs | 24 +- 20 files changed, 1140 insertions(+), 151 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs diff --git a/.gitignore b/.gitignore index 1768ebb161f..c0e9ed803ff 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,6 @@ # It's useful (though not required) to be able to unpack codeql in the ql checkout itself /codeql/ -.vscode/settings.json + csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json +.vscode diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs index db2664bf4c9..f93911b8a38 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs @@ -163,7 +163,19 @@ namespace Semmle.BuildAnalyser /// /// The filename to query. /// The assembly info. - public AssemblyInfo GetAssemblyInfo(string filepath) => assemblyInfo[filepath]; + public AssemblyInfo GetAssemblyInfo(string filepath) + { + if(assemblyInfo.TryGetValue(filepath, out var info)) + { + return info; + } + else + { + info = AssemblyInfo.ReadFromFile(filepath); + assemblyInfo.Add(filepath, info); + return info; + } + } // List of pending DLLs to index. readonly List dlls = new List(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs index b0ef328bcd0..dfc110c0d03 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs @@ -5,6 +5,8 @@ using System.Linq; using System.Runtime.InteropServices; using Semmle.Util; using Semmle.Extraction.CSharp.Standalone; +using System.Threading.Tasks; +using System.Collections.Concurrent; namespace Semmle.BuildAnalyser { @@ -56,6 +58,7 @@ namespace Semmle.BuildAnalyser int failedProjects, succeededProjects; readonly string[] allSources; int conflictedReferences = 0; + object mutex = new object(); /// /// Performs a C# build analysis. @@ -64,6 +67,8 @@ namespace Semmle.BuildAnalyser /// Display of analysis progress. public BuildAnalysis(Options options, IProgressMonitor progress) { + var startTime = DateTime.Now; + progressMonitor = progress; sourceDir = new DirectoryInfo(options.SrcDir); @@ -74,31 +79,43 @@ namespace Semmle.BuildAnalyser Where(d => !options.ExcludesFile(d)). ToArray(); - var dllDirNames = options.DllDirs.Select(Path.GetFullPath); + var dllDirNames = options.DllDirs.Select(Path.GetFullPath).ToList(); + PackageDirectory = TemporaryDirectory.CreateTempDirectory(sourceDir.FullName, progressMonitor); if (options.UseNuGet) { - nuget = new NugetPackages(sourceDir.FullName); - ReadNugetFiles(); - dllDirNames = dllDirNames.Concat(Enumerators.Singleton(nuget.PackageDirectory)); + try + { + nuget = new NugetPackages(sourceDir.FullName, PackageDirectory); + ReadNugetFiles(); + } + catch(FileNotFoundException) + { + progressMonitor.MissingNuGet(); + } } // Find DLLs in the .Net Framework if (options.ScanNetFrameworkDlls) { - dllDirNames = dllDirNames.Concat(Runtime.Runtimes.Take(1)); + dllDirNames.Add(Runtime.Runtimes.First()); } - - assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); - - // Analyse all .csproj files in the source tree. - if (options.SolutionFile != null) + { - AnalyseSolution(options.SolutionFile); - } - else if (options.AnalyseCsProjFiles) - { - AnalyseProjectFiles(); + using var renamer1 = new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories)); + using var renamer2 = new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories)); + + var solutions = options.SolutionFile != null ? + new[] { options.SolutionFile } : + sourceDir.GetFiles("*.sln", SearchOption.AllDirectories).Select(d => d.FullName); + + + RestoreSolutions(solutions); + dllDirNames.Add(PackageDirectory.DirInfo.FullName); + assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); + AnalyseSolutions(solutions); + + usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); } if (!options.AnalyseCsProjFiles) @@ -106,6 +123,7 @@ namespace Semmle.BuildAnalyser usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); } + ResolveConflicts(); if (options.UseMscorlib) @@ -133,6 +151,8 @@ namespace Semmle.BuildAnalyser conflictedReferences, succeededProjects + failedProjects, failedProjects); + + Console.WriteLine($"Build analysis completed in {DateTime.Now - startTime}"); } /// @@ -183,7 +203,8 @@ namespace Semmle.BuildAnalyser /// The filename of the reference. void UseReference(string reference) { - usedReferences.Add(reference); + lock (mutex) + usedReferences.Add(reference); } /// @@ -194,11 +215,13 @@ namespace Semmle.BuildAnalyser { if (sourceFile.Exists) { - usedSources.Add(sourceFile.FullName); + lock(mutex) + usedSources.Add(sourceFile.FullName); } else { - missingSources.Add(sourceFile.FullName); + lock(mutex) + missingSources.Add(sourceFile.FullName); } } @@ -236,59 +259,63 @@ namespace Semmle.BuildAnalyser /// The project file making the reference. void UnresolvedReference(string id, string projectFile) { - unresolvedReferences[id] = projectFile; + lock(mutex) + unresolvedReferences[id] = projectFile; } - /// - /// Performs an analysis of all .csproj files. - /// - void AnalyseProjectFiles() - { - AnalyseProjectFiles(sourceDir.GetFiles("*.csproj", SearchOption.AllDirectories)); - } + TemporaryDirectory PackageDirectory; /// /// Reads all the source files and references from the given list of projects. /// /// The list of projects to analyse. - void AnalyseProjectFiles(FileInfo[] projectFiles) + void AnalyseProjectFiles(IEnumerable projectFiles) { - progressMonitor.AnalysingProjectFiles(projectFiles.Count()); - foreach (var proj in projectFiles) + AnalyseProject(proj); + } + + void AnalyseProject(FileInfo project) + { + if(!project.Exists) { - try - { - var csProj = new CsProjFile(proj); - - foreach (var @ref in csProj.References) - { - AssemblyInfo resolved = assemblyCache.ResolveReference(@ref); - if (!resolved.Valid) - { - UnresolvedReference(@ref, proj.FullName); - } - else - { - UseReference(resolved.Filename); - } - } - - foreach (var src in csProj.Sources) - { - // Make a note of which source files the projects use. - // This information doesn't affect the build but is dumped - // as diagnostic output. - UseSource(new FileInfo(src)); - } - ++succeededProjects; - } - catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] - { - ++failedProjects; - progressMonitor.FailedProjectFile(proj.FullName, ex.Message); - } + progressMonitor.MissingProject(project.FullName); + return; } + + try + { + var csProj = new CsProjFile(project); + + foreach (var @ref in csProj.References) + { + AssemblyInfo resolved = assemblyCache.ResolveReference(@ref); + if (!resolved.Valid) + { + UnresolvedReference(@ref, project.FullName); + } + else + { + UseReference(resolved.Filename); + } + } + + foreach (var src in csProj.Sources) + { + // Make a note of which source files the projects use. + // This information doesn't affect the build but is dumped + // as diagnostic output. + UseSource(new FileInfo(src)); + } + + ++succeededProjects; + } + catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] + { + ++failedProjects; + progressMonitor.FailedProjectFile(project.FullName, ex.Message); + } + } /// @@ -296,17 +323,36 @@ namespace Semmle.BuildAnalyser /// public void Cleanup() { - if (nuget != null) nuget.Cleanup(progressMonitor); + PackageDirectory?.Cleanup(); } - /// - /// Analyse all project files in a given solution only. - /// - /// The filename of the solution. - public void AnalyseSolution(string solutionFile) + void Restore(string projectOrSolution) { - var sln = new SolutionFile(solutionFile); - AnalyseProjectFiles(sln.Projects.Select(p => new FileInfo(p)).ToArray()); + int exit = DotNet.RestoreToDirectory(projectOrSolution, PackageDirectory.DirInfo.FullName); + if (exit != 0) + progressMonitor.CommandFailed("dotnet", $"restore \"{projectOrSolution}\"", exit); + } + + public void RestoreSolutions(IEnumerable solutions) + { + Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 }, Restore); + } + + public void AnalyseSolutions(IEnumerable solutions) + { + Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 } , solutionFile => + { + try + { + var sln = new SolutionFile(solutionFile); + progressMonitor.AnalysingSolution(solutionFile); + AnalyseProjectFiles(sln.Projects.Select(p => new FileInfo(p)).Where(p => p.Exists).ToArray()); + } + catch (Microsoft.Build.Exceptions.InvalidProjectFileException ex) + { + progressMonitor.FailedProjectFile(solutionFile, ex.BaseMessage); + } + }); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs index 2c9e72c1eaa..02391c6eb7c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs @@ -5,17 +5,97 @@ using System.Xml; namespace Semmle.BuildAnalyser { + /// + /// A reference to a particular version of a particular package. + /// + class PackageReference + { + public PackageReference(string include, string version) { + Include = include; + Version = version; + } + public string Include, Version; + + public override string ToString() => $"Include={Include}, Version={Version}"; + } + + enum ProjectFileType + { + MsBuildProject, + DotNetProject, + OtherProject + } + + interface IProjectFile + { + IEnumerable ProjectReferences { get; } + + IEnumerable Packages { get; } + + IEnumerable References { get; } + + IEnumerable Sources { get; } + + IEnumerable TargetFrameworks { get; } + } + + class NetCoreProjectFile : IProjectFile + { + FileInfo path; + XmlDocument doc; + XmlElement root; + + public NetCoreProjectFile(FileInfo path) + { + this.path = path; + doc = new XmlDocument(); + doc.Load(path.FullName); + root = doc.DocumentElement; + } + + public IEnumerable ProjectReferences => throw new System.NotImplementedException(); + + public IEnumerable Packages + { + get + { + var packages = root.SelectNodes("/Project/ItemGroup/PackageReference"); + return packages.NodeList(). + Select(r => + new PackageReference(r.Attributes.GetNamedItem("Include").Value, r.Attributes.GetNamedItem("Version").Value)); + } + } + + public IEnumerable References => throw new System.NotImplementedException(); + + public IEnumerable Sources + { + get + { + return path.Directory.GetFiles("*.cs", SearchOption.AllDirectories); + } + } + + public IEnumerable TargetFrameworks => throw new System.NotImplementedException(); + } + /// /// Represents a .csproj file and reads information from it. /// class CsProjFile { + public string Filename { get; } + + public string Directory => Path.GetDirectoryName(Filename); + /// /// Reads the .csproj file. /// /// The .csproj file. public CsProjFile(FileInfo filename) { + Filename = filename.FullName; + try { // This can fail if the .csproj is invalid or has @@ -56,6 +136,8 @@ namespace Semmle.BuildAnalyser .ToArray(); } + string[] targetFrameworks = new string[0]; + /// /// Reads the .csproj file directly as XML. /// This doesn't handle variables etc, and should only used as a @@ -71,6 +153,35 @@ namespace Semmle.BuildAnalyser var projDir = filename.Directory; var root = projFile.DocumentElement; + // Figure out if it's dotnet core + + bool netCoreProjectFile = root.GetAttribute("Sdk") == "Microsoft.NET.Sdk"; + + if(netCoreProjectFile) + { + var frameworksNode = root.SelectNodes("/Project/PropertyGroup/TargetFrameworks").NodeList().Concat( + root.SelectNodes("/Project/PropertyGroup/TargetFramework").NodeList()).Select(node => node.InnerText); + + targetFrameworks = frameworksNode.SelectMany(node => node.Split(";")).ToArray(); + + var relativeCsIncludes2 = + root.SelectNodes("/Project/ItemGroup/Compile/@Include", mgr). + NodeList(). + Select(node => node.Value). + ToArray(); + + var explicitCsFiles = relativeCsIncludes2. + Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs). + Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))); + + var additionalCsFiles = System.IO.Directory.GetFiles(Directory, "*.cs", SearchOption.AllDirectories); + + csFiles = explicitCsFiles.Concat(additionalCsFiles).ToArray(); + + references = new string[0]; + return; + } + references = root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Reference/@Include", mgr). NodeList(). @@ -97,6 +208,8 @@ namespace Semmle.BuildAnalyser /// public IEnumerable References => references; + public IEnumerable TargetFrameworks => targetFrameworks; + /// /// The list of C# source files in full path format. /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs new file mode 100644 index 00000000000..6d36892c7c9 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace Semmle.BuildAnalyser +{ + /// + /// Utilities to run the "dotnet" command. + /// + static class DotNet + { + public static int RestoreToDirectory(string projectOrSolutionFile, string packageDirectory) + { + using var proc = Process.Start("dotnet", $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\""); + proc.WaitForExit(); + return proc.ExitCode; + } + } + + /// + /// Utility to temporarily rename a set of files. + /// + class FileRenamer : IDisposable + { + string[] files; + const string suffix = ".codeqlhidden"; + + public FileRenamer(IEnumerable oldFiles) + { + files = oldFiles.Select(f => f.FullName).ToArray(); + + foreach(var file in files) + { + File.Move(file, file + suffix); + } + } + + public void Dispose() + { + foreach (var file in files) + { + File.Move(file + suffix, file); + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs new file mode 100644 index 00000000000..21fe4a22338 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Concurrent; +using System.Diagnostics; + +namespace RoslynWS +{ + /// + /// Information about the .NET Core runtime. + /// + public class DotNetRuntimeInfo + { + /// + /// A cache of .NET runtime information by target directory. + /// + static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); + + /// + /// The .NET Core version. + /// + public string Version { get; set; } + + /// + /// The .NET Core base directory. + /// + public string BaseDirectory { get; set; } + + /// + /// The current runtime identifier (RID). + /// + public string RID { get; set; } + + /// + /// Get information about the current .NET Core runtime. + /// + /// + /// An optional base directory where dotnet.exe should be run (this may affect the version it reports due to global.json). + /// + /// + /// A containing the runtime information. + /// + public static DotNetRuntimeInfo GetCurrent(string baseDirectory = null) + { + return _cache.GetOrAdd(baseDirectory, _ => + { + DotNetRuntimeInfo runtimeInfo = new DotNetRuntimeInfo(); + + Process dotnetInfoProcess = Process.Start(new ProcessStartInfo + { + FileName = "dotnet", + WorkingDirectory = baseDirectory, + Arguments = "--info", + UseShellExecute = false, + RedirectStandardOutput = true + }); + using (dotnetInfoProcess) + { + dotnetInfoProcess.WaitForExit(); + + string currentSection = null; + string currentLine; + while ((currentLine = dotnetInfoProcess.StandardOutput.ReadLine()) != null) + { + if (String.IsNullOrWhiteSpace(currentLine)) + continue; + + if (!currentLine.StartsWith(" ")) + { + currentSection = currentLine; + + continue; + } + + string[] property = currentLine.Split(new char[] { ':' }, count: 2); + if (property.Length != 2) + continue; + + property[0] = property[0].Trim(); + property[1] = property[1].Trim(); + + switch (currentSection) + { + case "Product Information:": + { + switch (property[0]) + { + case "Version": + { + runtimeInfo.Version = property[1]; + + break; + } + } + + break; + } + case "Runtime Environment:": + { + switch (property[0]) + { + case "Base Path": + { + runtimeInfo.BaseDirectory = property[1]; + + break; + } + case "RID": + { + runtimeInfo.RID = property[1]; + + break; + } + } + + break; + } + } + } + } + + return runtimeInfo; + }); + } + + /// + /// Clear the cache of .NET runtime information. + /// + public static void ClearCache() + { + _cache.Clear(); + } + } +} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs new file mode 100644 index 00000000000..cbba36e8419 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs @@ -0,0 +1,260 @@ + +using Microsoft.Build.Construction; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Exceptions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Collections.Immutable; + +namespace RoslynWS +{ + /// + /// Helper methods for working with MSBuild projects. + /// + public static class MSBuildHelper + { + /// + /// The names of well-known item metadata. + /// + public static readonly ImmutableSortedSet WellknownMetadataNames = + ImmutableSortedSet.Create( + "FullPath", + "RootDir", + "Filename", + "Extension", + "RelativeDir", + "Directory", + "RecursiveDir", + "Identity", + "ModifiedTime", + "CreatedTime", + "AccessedTime" + ); + + /// + /// Create an MSBuild project collection. + /// + /// + /// The base (i.e. solution) directory. + /// + /// + /// The project collection. + /// + public static ProjectCollection CreateProjectCollection(string solutionDirectory) + { + return CreateProjectCollection(solutionDirectory, + DotNetRuntimeInfo.GetCurrent(solutionDirectory) + ); + } + + /// + /// Create an MSBuild project collection. + /// + /// + /// The base (i.e. solution) directory. + /// + /// + /// Information about the current .NET Core runtime. + /// + /// + /// The project collection. + /// + public static ProjectCollection CreateProjectCollection(string solutionDirectory, DotNetRuntimeInfo runtimeInfo) + { + if (String.IsNullOrWhiteSpace(solutionDirectory)) + throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'baseDir'.", nameof(solutionDirectory)); + + if (runtimeInfo == null) + throw new ArgumentNullException(nameof(runtimeInfo)); + + if (String.IsNullOrWhiteSpace(runtimeInfo.BaseDirectory)) + throw new InvalidOperationException("Cannot determine base directory for .NET Core."); + + Dictionary globalProperties = CreateGlobalMSBuildProperties(runtimeInfo, solutionDirectory); + EnsureMSBuildEnvironment(globalProperties); + + ProjectCollection projectCollection = new ProjectCollection(globalProperties) { IsBuildEnabled = false }; + + // Override toolset paths (for some reason these point to the main directory where the dotnet executable lives). + Toolset toolset = projectCollection.GetToolset("15.0"); + toolset = new Toolset( + toolsVersion: "15.0", + toolsPath: globalProperties["MSBuildExtensionsPath"], + projectCollection: projectCollection, + msbuildOverrideTasksPath: "" + ); + projectCollection.AddToolset(toolset); + + return projectCollection; + } + + /// + /// Create global properties for MSBuild. + /// + /// + /// Information about the current .NET Core runtime. + /// + /// + /// The base (i.e. solution) directory. + /// + /// + /// A dictionary containing the global properties. + /// + public static Dictionary CreateGlobalMSBuildProperties(DotNetRuntimeInfo runtimeInfo, string solutionDirectory) + { + if (runtimeInfo == null) + throw new ArgumentNullException(nameof(runtimeInfo)); + + if (String.IsNullOrWhiteSpace(solutionDirectory)) + throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'solutionDirectory'.", nameof(solutionDirectory)); + + if (solutionDirectory.Length > 0 && solutionDirectory[solutionDirectory.Length - 1] != Path.DirectorySeparatorChar) + solutionDirectory += Path.DirectorySeparatorChar; + + return new Dictionary + { + [WellKnownPropertyNames.DesignTimeBuild] = "true", + [WellKnownPropertyNames.BuildProjectReferences] = "false", + [WellKnownPropertyNames.ResolveReferenceDependencies] = "true", + [WellKnownPropertyNames.SolutionDir] = solutionDirectory, + [WellKnownPropertyNames.MSBuildExtensionsPath] = runtimeInfo.BaseDirectory, + [WellKnownPropertyNames.MSBuildSDKsPath] = Path.Combine(runtimeInfo.BaseDirectory, "Sdks"), + [WellKnownPropertyNames.RoslynTargetsPath] = Path.Combine(runtimeInfo.BaseDirectory, "Roslyn") + }; + } + + /// + /// Ensure that environment variables are populated using the specified MSBuild global properties. + /// + /// + /// The MSBuild global properties + /// + public static void EnsureMSBuildEnvironment(Dictionary globalMSBuildProperties) + { + if (globalMSBuildProperties == null) + throw new ArgumentNullException(nameof(globalMSBuildProperties)); + + // Kinda sucks that the simplest way to get MSBuild to resolve SDKs correctly is using environment variables, but there you go. + Environment.SetEnvironmentVariable( + WellKnownPropertyNames.MSBuildExtensionsPath, + globalMSBuildProperties[WellKnownPropertyNames.MSBuildExtensionsPath] + ); + Environment.SetEnvironmentVariable( + WellKnownPropertyNames.MSBuildSDKsPath, + globalMSBuildProperties[WellKnownPropertyNames.MSBuildSDKsPath] + ); + } + + /// + /// Does the specified property name represent a private property? + /// + /// + /// The property name. + /// + /// + /// true, if the property name starts with an underscore; otherwise, false. + /// + public static bool IsPrivateProperty(string propertyName) => propertyName?.StartsWith("_") ?? false; + + /// + /// Does the specified metadata name represent a private property? + /// + /// + /// The metadata name. + /// + /// + /// true, if the metadata name starts with an underscore; otherwise, false. + /// + public static bool IsPrivateMetadata(string metadataName) => metadataName?.StartsWith("_") ?? false; + + /// + /// Does the specified item type represent a private property? + /// + /// + /// The item type. + /// + /// + /// true, if the item type starts with an underscore; otherwise, false. + /// + public static bool IsPrivateItemType(string itemType) => itemType?.StartsWith("_") ?? false; + + /// + /// Determine whether the specified metadata name represents well-known (built-in) item metadata. + /// + /// + /// The metadata name. + /// + /// + /// true, if represents well-known item metadata; otherwise, false. + /// + public static bool IsWellKnownItemMetadata(string metadataName) => WellknownMetadataNames.Contains(metadataName); + + /// + /// Create a copy of the project for caching. + /// + /// + /// The MSBuild project. + /// + /// + /// The project copy (independent of original, but sharing the same ). + /// + /// + /// You can only create a single cached copy for a given project. + /// + public static Project CloneAsCachedProject(this Project project) + { + if (project == null) + throw new ArgumentNullException(nameof(project)); + + ProjectRootElement clonedXml = project.Xml.DeepClone(); + Project clonedProject = new Project(clonedXml, project.GlobalProperties, project.ToolsVersion, project.ProjectCollection); + clonedProject.FullPath = Path.ChangeExtension(project.FullPath, + ".cached" + Path.GetExtension(project.FullPath) + ); + + return clonedProject; + } + + /// + /// The names of well-known MSBuild properties. + /// + public static class WellKnownPropertyNames + { + /// + /// The "MSBuildExtensionsPath" property. + /// + public static readonly string MSBuildExtensionsPath = "MSBuildExtensionsPath"; + + /// + /// The "MSBuildSDKsPath" property. + /// + public static readonly string MSBuildSDKsPath = "MSBuildSDKsPath"; + + /// + /// The "SolutionDir" property. + /// + public static readonly string SolutionDir = "SolutionDir"; + + /// + /// The "_ResolveReferenceDependencies" property. + /// + public static readonly string ResolveReferenceDependencies = "_ResolveReferenceDependencies"; + + /// + /// The "DesignTimeBuild" property. + /// + public static readonly string DesignTimeBuild = "DesignTimeBuild"; + + /// + /// The "BuildProjectReferences" property. + /// + public static readonly string BuildProjectReferences = "BuildProjectReferences"; + + /// + /// The "RoslynTargetsPath" property. + /// + public static readonly string RoslynTargetsPath = "RoslynTargetsPath"; + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs new file mode 100644 index 00000000000..3b84df7463c --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs @@ -0,0 +1,357 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace Semmle.BuildAnalyser +{ + /// + /// A package in a NuGet package repository. + /// For example, the directory C:\Users\calum\.nuget\packages\microsoft.visualbasic. + /// + /// Each package contains a number of subdirectories, organised by version. + /// + class Package + { + public readonly string directory; + + /// + /// Constructs a package for the given directory. + /// + /// The directory. + public Package(string dir) + { + directory = dir; + } + + /// + /// The name of the package. + /// + public string Name => Path.GetDirectoryName(directory); + + /// + /// The versions that exist within the package. + /// + public IEnumerable Versions => Directory.GetDirectories(directory).Select(dir => new PackageVersion(dir)); + + public override string ToString() => Path.GetFileName(directory); + + public PackageVersion FindVersion(string version) + { + if (Directory.Exists(Path.Combine(directory, version))) + return new PackageVersion(Path.Combine(directory, version)); + else + return Versions.OrderByDescending(v => v.Version).First(); + } + + /// + /// Locates the exact version of a particular package. + /// + /// The version to locate. + /// The specific version of the package. + public PackageVersion FindExactVersion(string version) + { + if (Directory.Exists(Path.Combine(directory, version))) + return new PackageVersion(Path.Combine(directory, version)); + else + return null; + } + } + + /// + /// A package in a NuGet package respository, including the specific version. + /// For example, the directory C:\Users\calum\.nuget\packages\microsoft.visualbasic\10.0.1 + /// + class PackageVersion + { + readonly string directory; + + /// + /// The version of the package. + /// + public string Version => Path.GetFileName(directory); + + /// + /// Constructs a package version from its directory. + /// + /// The directory of this package. + public PackageVersion(string directory) + { + if (!Directory.Exists(directory)) + throw new DirectoryNotFoundException(directory); + + this.directory = directory; + } + + public override string ToString() => Version; + + /// + /// The frameworks within this package. + /// Sometimes a directory references several frameworks, for example + /// "net451+netstandard2.0". This are split into separate frameworks. + /// + IEnumerable UnorderedFrameworks + { + get + { + return UnorderedFrameworksInDirectory(Path.Combine(directory, "lib")). + Concat(UnorderedFrameworksInDirectory(Path.Combine(directory, "ref"))). + Concat(UnorderedFrameworksInDirectory(Path.Combine(directory, "build", "lib"))). + Concat(UnorderedFrameworksInDirectory(Path.Combine(directory, "build", "ref"))). + Concat(TryDirectory(Path.Combine(directory, "lib"))); + } + } + + IEnumerable TryDirectory(string directory) + { + if (Directory.Exists(directory)) + yield return new PackageFramework(directory, "unknown"); + } + + IEnumerable UnorderedFrameworksInDirectory(string lib) + { + if (!Directory.Exists(lib)) + yield break; + foreach (var p in System.IO.Directory.GetDirectories(lib)) + { + var name = Path.GetFileName(p); + if (name.Contains('+')) + { + foreach (var p2 in name.Split('+')) + yield return new PackageFramework(p, p2); + } + else + yield return new PackageFramework(p, name); + } + } + + /// + /// The frameworks in this package, in a consistent sequence, with the "best" frameworks + /// appearing at the start of the list. + /// + /// Priorities "netstandard" framework, followed by "netcoreapp", followed by everything else. + /// Then, selects the highest version number. + /// + public IEnumerable Frameworks => + UnorderedFrameworks. + OrderBy(framework => framework.Framework.StartsWith("netstandard") ? 0 : framework.Framework.StartsWith("netcoreapp") ? 1 : 2). + ThenByDescending(framework => framework.Framework); + + /// + /// Finds the best framework containing references. + /// Returns null if no suitable framework was found. + /// + public PackageFramework? BestFramework => Frameworks.Where(f => f.References.Any()).FirstOrDefault(); + + public bool ContainsLibraries + { + get + { + return Directory.Exists(Path.Combine(directory, "lib")) || + Directory.Exists(Path.Combine(directory, "ref")) || + Directory.Exists(Path.Combine(directory, "build", "lib")) || + Directory.Exists(Path.Combine(directory, "build", "ref")); + } + } + + public bool ContainsDLLs + { + get + { + return Directory.GetFiles(directory, "*.dll", SearchOption.AllDirectories).Any(); + } + } + } + + /// + /// A framework in a package. + /// For example, C:\Users\calum\.nuget\packages\microsoft.testplatform.objectmodel\16.4.0\lib\netstandard2.0 + /// + class PackageFramework + { + public string Directory { get; } + + /// + /// The framework name. + /// + public string Framework { get; } + + /// + /// Constructs a package framework from a directory. + /// The framework is needed because the directory may specify more than one framework. + /// + /// The directory path. + /// The framework. + public PackageFramework(string dir, string framework) + { + if (!System.IO.Directory.Exists(dir)) + throw new FileNotFoundException(dir); + Directory = dir; + Framework = framework; + } + + /// + /// The reference DLLs contained within the directory. + /// + public IEnumerable References + { + get + { + return new DirectoryInfo(Directory).GetFiles("*.dll").Select(fi => fi.FullName); + } + } + + public override string ToString() => Directory; + } + + class TemporaryDirectory : IDisposable + { + readonly IProgressMonitor ProgressMonitor; + + public DirectoryInfo DirInfo { get; } + + public TemporaryDirectory(string name, IProgressMonitor pm) + { + ProgressMonitor = pm; + DirInfo = new DirectoryInfo(name); + DirInfo.Create(); + } + + /// + /// Computes a unique temp directory for the packages associated + /// with this source tree. Use a SHA1 of the directory name. + /// + /// + /// The full path of the temp directory. + public static string ComputeTempDirectory(string srcDir) + { + var bytes = Encoding.Unicode.GetBytes(srcDir); + + var sha1 = new SHA1CryptoServiceProvider(); + var sha = sha1.ComputeHash(bytes); + var sb = new StringBuilder(); + foreach (var b in sha.Take(8)) + sb.AppendFormat("{0:x2}", b); + + return Path.Combine(Path.GetTempPath(), "GitHub", "packages", sb.ToString()); + } + + public static TemporaryDirectory CreateTempDirectory(string source, IProgressMonitor pm) => new TemporaryDirectory(ComputeTempDirectory(source), pm); + + public void Cleanup() + { + try + { + DirInfo.Delete(true); + } + catch (System.IO.IOException ex) + { + ProgressMonitor.Warning(string.Format("Couldn't delete package directory - it's probably held open by something else: {0}", ex.Message)); + } + + } + + public void Dispose() + { + Cleanup(); + } + + public override string ToString() => DirInfo.FullName.ToString(); + } + + /// + /// The NuGet package repository. + /// + class NugetPackageRepository + { + // A list of package directories, in the order they should be searched. + private readonly string[] packageDirs; + + public NugetPackageRepository(params string[] dirs) + { + packageDirs = dirs; + } + + /// + /// Constructs a NuGet package repository, using the default locations. + /// For example, + /// $HOME/.nuget/packages, /usr/share/dotnet/sdk/NuGetFallbackFolder + /// + public NugetPackageRepository(string sourceDir) + { + var homeFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var nugetPackages = Path.Combine(homeFolder, ".nuget", "packages"); + var nugetFallbackFolder = Environment.OSVersion.Platform == PlatformID.Win32NT ? + @"C:\Program Files\dotnet\sdk\NuGetFallbackFolder" : + "/usr/share/dotnet/sdk/NuGetFallbackFolder"; + + packageDirs = new string[] { nugetPackages, nugetFallbackFolder }; + } + + /// + /// Enumerate all available packages. + /// + public IEnumerable Packages + { + get + { + foreach (var d in packageDirs) + foreach (var p in Directory.GetDirectories(d)) + { + var name = Path.GetFileName(p); + if (!name.StartsWith('.')) + yield return new Package(p); + } + } + } + + /// + /// Tries to find a PackageFramework directory for a given package reference. + /// + /// The package reference to search for. + /// The package that was found. + /// True if a package/version/framework was found. + public bool TryFindLibs(PackageReference reference, out PackageFramework package, out ResolutionFailureReason reason) + { + var packages = packageDirs. + Where(d => Directory.Exists(Path.Combine(d, reference.Include.ToLowerInvariant()))). + Select(d => new Package(Path.Combine(d, reference.Include.ToLowerInvariant()))); + + if(!packages.Any()) + { + reason = ResolutionFailureReason.PackageNotFound; + package = null; + return false; + } + + var version = packages.Select(p => p.FindVersion(reference.Version)).FirstOrDefault(v => !(v is null)); + + if (version is null) + { + reason = ResolutionFailureReason.VersionNotFound; + package = null; + return false; + } + + package = version.BestFramework; + if(package is null) + { + reason = ResolutionFailureReason.LibsNotFound; + return false; + } + + reason = ResolutionFailureReason.Success; + return true; + } + } + + enum ResolutionFailureReason + { + Success, + PackageNotFound, + VersionNotFound, + LibsNotFound + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs index 1f0755f307f..0fc207f2049 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs @@ -19,10 +19,10 @@ namespace Semmle.BuildAnalyser /// Create the package manager for a specified source tree. /// /// The source directory. - public NugetPackages(string sourceDir) + public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory) { SourceDirectory = sourceDir; - PackageDirectory = computeTempDirectory(sourceDir); + PackageDirectory = packageDirectory; // Expect nuget.exe to be in a `nuget` directory under the directory containing this exe. var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location; @@ -50,45 +50,12 @@ namespace Semmle.BuildAnalyser /// public IEnumerable PackageFiles => packages; - // Whether to delete the packages directory prior to each run. - // Makes each build more reproducible. - const bool cleanupPackages = true; - - public void Cleanup(IProgressMonitor pm) - { - var packagesDirectory = new DirectoryInfo(PackageDirectory); - - if (packagesDirectory.Exists) - { - try - { - packagesDirectory.Delete(true); - } - catch (System.IO.IOException ex) - { - pm.Warning(string.Format("Couldn't delete package directory - it's probably held open by something else: {0}", ex.Message)); - } - } - } - /// /// Download the packages to the temp folder. /// /// The progress monitor used for reporting errors etc. public void InstallPackages(IProgressMonitor pm) { - if (cleanupPackages) - { - Cleanup(pm); - } - - var packagesDirectory = new DirectoryInfo(PackageDirectory); - - if (!Directory.Exists(PackageDirectory)) - { - packagesDirectory.Create(); - } - foreach (var package in packages) { RestoreNugetPackage(package.FullName, pm); @@ -109,31 +76,7 @@ namespace Semmle.BuildAnalyser /// This will be in the Temp location /// so as to not trample the source tree. /// - public string PackageDirectory - { - get; - private set; - } - - readonly SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); - - /// - /// Computes a unique temp directory for the packages associated - /// with this source tree. Use a SHA1 of the directory name. - /// - /// - /// The full path of the temp directory. - string computeTempDirectory(string srcDir) - { - var bytes = Encoding.Unicode.GetBytes(srcDir); - - var sha = sha1.ComputeHash(bytes); - var sb = new StringBuilder(); - foreach (var b in sha.Take(8)) - sb.AppendFormat("{0:x2}", b); - - return Path.Combine(Path.GetTempPath(), "Semmle", "packages", sb.ToString()); - } + public TemporaryDirectory PackageDirectory { get; } /// /// Restore all files in a specified package. diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs index e0367fa63c1..3ba368f6da0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs @@ -3,6 +3,11 @@ using System.Collections.Generic; using System.Linq; using Semmle.BuildAnalyser; using Semmle.Util.Logging; +using System.IO; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +// using Microsoft.Build.Locator; namespace Semmle.Extraction.CSharp.Standalone { @@ -82,9 +87,15 @@ namespace Semmle.Extraction.CSharp.Standalone public class Program { + void LoadSolutionFile(string file) + { + + } + static int Main(string[] args) { var options = Options.Create(args); + options.CIL = true; var output = new ConsoleLogger(options.Verbosity); var a = new Analysis(output); @@ -97,6 +108,8 @@ namespace Semmle.Extraction.CSharp.Standalone if (options.Errors) return 1; + var start = DateTime.Now; + output.Log(Severity.Info, "Running C# standalone extractor"); a.AnalyseProjects(options); int sourceFiles = a.Extraction.Sources.Count(); @@ -117,7 +130,7 @@ namespace Semmle.Extraction.CSharp.Standalone new ExtractionProgress(output), new FileLogger(options.Verbosity, Extractor.GetCSharpLogPath()), options); - output.Log(Severity.Info, "Extraction complete"); + output.Log(Severity.Info, $"Extraction completed in {DateTime.Now-start}"); } a.Cleanup(); @@ -151,7 +164,7 @@ namespace Semmle.Extraction.CSharp.Standalone public void MissingSummary(int missingTypes, int missingNamespaces) { - logger.Log(Severity.Info, "Failed to resolve {0} types and {1} namespaces", missingTypes, missingNamespaces); + logger.Log(Severity.Info, "Failed to resolve {0} types in {1} namespaces", missingTypes, missingNamespaces); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs index f4bde55ec55..a004e59eb13 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs @@ -10,6 +10,7 @@ namespace Semmle.BuildAnalyser void FindingFiles(string dir); void UnresolvedReference(string id, string project); void AnalysingProjectFiles(int count); + void AnalysingSolution(string filename); void FailedProjectFile(string filename, string reason); void FailedNugetCommand(string exe, string args, string message); void NugetInstall(string package); @@ -18,6 +19,11 @@ namespace Semmle.BuildAnalyser void Warning(string message); void ResolvedConflict(string asm1, string asm2); void MissingProject(string projectFile); + void Restored(string line); + void MissingPackage(string package, string version, ResolutionFailureReason reason); + void FoundPackage(string package, string version, string directory); + void CommandFailed(string exe, string arguments, int exitCode); + void MissingNuGet(); } class ProgressMonitor : IProgressMonitor @@ -51,6 +57,11 @@ namespace Semmle.BuildAnalyser logger.Log(Severity.Info, "Analyzing project files..."); } + public void AnalysingSolution(string filename) + { + logger.Log(Severity.Info, $"Analysing {filename}..."); + } + public void FailedProjectFile(string filename, string reason) { logger.Log(Severity.Info, "Couldn't read project file {0}: {1}", filename, reason); @@ -73,7 +84,8 @@ namespace Semmle.BuildAnalyser } public void Summary(int existingSources, int usedSources, int missingSources, - int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects) + int references, int unresolvedReferences, + int resolvedConflicts, int totalProjects, int failedProjects) { logger.Log(Severity.Info, ""); logger.Log(Severity.Info, "Build analysis summary:"); @@ -87,6 +99,23 @@ namespace Semmle.BuildAnalyser logger.Log(Severity.Info, "{0, 6} missing/failed projects", failedProjects); } + public void Restored(string line) + { + logger.Log(Severity.Debug, $" {line}"); + } + + private static string[] reasonText = { "success", "package was not found", "the version was not found", "the package does not appear to contain any libraries" }; + + public void MissingPackage(string package, string version, ResolutionFailureReason reason) + { + logger.Log(Severity.Info, $" Couldn't find package {package} {version} because {reasonText[(int)reason]}"); + } + + public void FoundPackage(string package, string version, string directory) + { + logger.Log(Severity.Debug, $" Found package {package} {version} in {directory}"); + } + public void Warning(string message) { logger.Log(Severity.Warning, message); @@ -94,12 +123,22 @@ namespace Semmle.BuildAnalyser public void ResolvedConflict(string asm1, string asm2) { - logger.Log(Severity.Info, "Resolved {0} as {1}", asm1, asm2); + logger.Log(Severity.Debug, "Resolved {0} as {1}", asm1, asm2); } public void MissingProject(string projectFile) { logger.Log(Severity.Info, "Solution is missing {0}", projectFile); } + + public void CommandFailed(string exe, string arguments, int exitCode) + { + logger.Log(Severity.Error, $"Command {exe} {arguments} failed with exit code {exitCode}"); + } + + public void MissingNuGet() + { + logger.Log(Severity.Error, "Missing nuget.exe"); + } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj index 4cf0274b737..1d4ab57d2d8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj @@ -1,4 +1,4 @@ - + Exe @@ -21,7 +21,10 @@ - + + + + diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs index b1a3edd4cf6..ffaebe360fe 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs @@ -11,6 +11,7 @@ namespace Semmle.BuildAnalyser class SolutionFile { readonly Microsoft.Build.Construction.SolutionFile solutionFile; + public string FullPath { get; } /// /// Read the file. @@ -19,8 +20,8 @@ namespace Semmle.BuildAnalyser public SolutionFile(string filename) { // SolutionFile.Parse() expects a rooted path. - var fullPath = Path.GetFullPath(filename); - solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(fullPath); + FullPath = Path.GetFullPath(filename); + solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(FullPath); } /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs index 0488fe84ffe..6962e8381d9 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs @@ -45,7 +45,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions Access(ExpressionNodeInfo info, ISymbol symbol, bool implicitThis, IEntity target) : base(info.SetKind(AccessKind(info.Context, symbol))) { - cx.TrapWriter.Writer.expr_access(this, target); + if (!(target is null)) + { + cx.TrapWriter.Writer.expr_access(this, target); + } if (implicitThis && !symbol.IsStatic) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs index e41ef0edf23..0bc84ca9c0c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs @@ -71,7 +71,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions if (symbol == null) { info.Context.ModelError(info.Node, "Failed to determine symbol for member access"); - return new MemberAccess(info.SetKind(ExprKind.UNKNOWN), expression, symbol); + // Default to property access - this can still give useful results but + // the target of the expression should be checked in QL. + return new MemberAccess(info.SetKind(ExprKind.PROPERTY_ACCESS), expression, symbol); } ExprKind kind; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index e22d32c0d01..cecec5bc028 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -25,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities { if (symbol.TypeKind == TypeKind.Error) { - Context.Extractor.MissingType(symbol.ToString()); + Context.Extractor.MissingType(symbol.ToString(), Context.FromSource); return; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs index 4fdbe7c18ad..02b67efc164 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs @@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities if (namespaceSymbol == null) { - cx.Extractor.MissingNamespace(Node.Name.ToFullString()); + cx.Extractor.MissingNamespace(Node.Name.ToFullString(), cx.FromSource); cx.ModelError(Node, "Namespace not found"); return; } diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index 93f99381858..918642f198d 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -155,7 +155,7 @@ namespace Semmle.Extraction #if DEBUG_LABELS using (var id = new StringWriter()) { - entity.WriteId(id); + entity.WriteQuotedId(id); CheckEntityHasUniqueLabel(id.ToString(), entity); } #endif @@ -270,6 +270,8 @@ namespace Semmle.Extraction TrapWriter = trapWriter; } + public bool FromSource => Scope.FromSource; + public bool IsGlobalContext => Scope.IsGlobalScope; public readonly ICommentGenerator CommentGenerator = new CommentProcessor(); diff --git a/csharp/extractor/Semmle.Extraction/ExtractionScope.cs b/csharp/extractor/Semmle.Extraction/ExtractionScope.cs index 7f4f599fe5c..60daff8d013 100644 --- a/csharp/extractor/Semmle.Extraction/ExtractionScope.cs +++ b/csharp/extractor/Semmle.Extraction/ExtractionScope.cs @@ -25,6 +25,8 @@ namespace Semmle.Extraction bool InFileScope(string path); bool IsGlobalScope { get; } + + bool FromSource { get; } } /// @@ -49,6 +51,8 @@ namespace Semmle.Extraction public bool InScope(ISymbol symbol) => SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, assembly) || SymbolEqualityComparer.Default.Equals(symbol, assembly); + + public bool FromSource => false; } /// @@ -68,5 +72,7 @@ namespace Semmle.Extraction public bool InFileScope(string path) => path == sourceTree.FilePath; public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == sourceTree); + + public bool FromSource => true; } } diff --git a/csharp/extractor/Semmle.Extraction/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor.cs index e470d3258ec..e1ca23f645b 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor.cs @@ -50,13 +50,15 @@ namespace Semmle.Extraction /// Record a new error type. /// /// The display name of the type, qualified where possible. - void MissingType(string fqn); + /// The missing type was referenced from a source file. + void MissingType(string fqn, bool fromSource); /// /// Record an unresolved `using namespace` directive. /// /// The full name of the namespace. - void MissingNamespace(string fqn); + /// The missing namespace was referenced from a source file. + void MissingNamespace(string fqn, bool fromSource); /// /// The list of missing types. @@ -167,16 +169,22 @@ namespace Semmle.Extraction readonly ISet missingTypes = new SortedSet(); readonly ISet missingNamespaces = new SortedSet(); - public void MissingType(string fqn) + public void MissingType(string fqn, bool fromSource) { - lock (mutex) - missingTypes.Add(fqn); + if (fromSource) + { + lock (mutex) + missingTypes.Add(fqn); + } } - public void MissingNamespace(string fqdn) + public void MissingNamespace(string fqdn, bool fromSource) { - lock (mutex) - missingNamespaces.Add(fqdn); + if (fromSource) + { + lock (mutex) + missingNamespaces.Add(fqdn); + } } public Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope) From fddbce0b7bb8dc7e97971a0af7b01902954d1d49 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 25 Mar 2020 13:24:48 +0100 Subject: [PATCH 134/459] C#: Move all predefined sources and sinks into `security/dataflow/flow{sinks,sources}` --- .../Security Features/CWE-091/XMLInjection.ql | 2 +- .../CWE-114/AssemblyPathInjection.ql | 2 +- .../CWE-134/UncontrolledFormatString.ql | 4 +- .../Security Features/InsecureRandomness.ql | 2 +- .../flowsources/PublicCallableParameter.qll | 7 +- .../csharp/dataflow/flowsources/Remote.qll | 219 +----------------- .../security/dataflow/CleartextStorage.qll | 4 +- .../security/dataflow/CodeInjection.qll | 4 +- .../security/dataflow/CommandInjection.qll | 2 +- .../security/dataflow/ConditionalBypass.qll | 2 +- .../dataflow/ExposureOfPrivateInformation.qll | 4 +- .../security/dataflow/LDAPInjection.qll | 2 +- .../csharp/security/dataflow/LogForging.qll | 4 +- .../dataflow/MissingXMLValidation.qll | 2 +- .../code/csharp/security/dataflow/ReDoS.qll | 2 +- .../security/dataflow/RegexInjection.qll | 2 +- .../security/dataflow/ResourceInjection.qll | 4 +- .../csharp/security/dataflow/SqlInjection.qll | 4 +- .../csharp/security/dataflow/TaintedPath.qll | 2 +- .../dataflow/UnsafeDeserialization.qll | 2 +- .../csharp/security/dataflow/UrlRedirect.qll | 2 +- .../security/dataflow/XMLEntityInjection.qll | 2 +- .../security/dataflow/XPathInjection.qll | 2 +- .../code/csharp/security/dataflow/XSS.qll | 2 +- .../flowsinks}/ExternalLocationSink.qll | 0 .../dataflow/flowsources/Local.qll | 0 .../security/dataflow/flowsources/Remote.qll | 218 +++++++++++++++++ .../PublicCallableParameterFlowSource.cs | 17 -- ...publicCallableParameterFlowSource.expected | 2 - .../publicCallableParameterFlowSource.ql | 5 - .../flowsources/remote/remoteFlowSource.ql | 2 +- 31 files changed, 257 insertions(+), 271 deletions(-) rename csharp/ql/src/semmle/code/csharp/security/{sinks => dataflow/flowsinks}/ExternalLocationSink.qll (100%) rename csharp/ql/src/semmle/code/csharp/{ => security}/dataflow/flowsources/Local.qll (100%) create mode 100644 csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Remote.qll delete mode 100644 csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs delete mode 100644 csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected delete mode 100644 csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql diff --git a/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql b/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql index 6b9acf69e3c..ac9a3d90dbd 100644 --- a/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql +++ b/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql @@ -11,7 +11,7 @@ */ import csharp -import semmle.code.csharp.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Xml /** diff --git a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql index 2b87d61f193..0aab5e3181a 100644 --- a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql +++ b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql @@ -12,7 +12,7 @@ */ import csharp -import semmle.code.csharp.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.commons.Util /** diff --git a/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql b/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql index 1b42ea7399d..3b9d6af7d14 100644 --- a/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql +++ b/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql @@ -11,8 +11,8 @@ */ import csharp -import semmle.code.csharp.dataflow.flowsources.Remote -import semmle.code.csharp.dataflow.flowsources.Local +import semmle.code.csharp.security.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.dataflow.TaintTracking import semmle.code.csharp.frameworks.Format import DataFlow::PathGraph diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index bd16dda8816..ef1665819f7 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.Test import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph module Random { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.security.SensitiveActions /** diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll index 07dc38d320d..7c6700c6637 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll @@ -1,11 +1,14 @@ /** + * DEPRECATED. + * * Provides classes representing data flow sources for parameters of public callables. */ import csharp -private import semmle.code.csharp.frameworks.WCF /** + * DEPRECATED. + * * A parameter of a public callable, for example `p` in * * ``` @@ -14,7 +17,7 @@ private import semmle.code.csharp.frameworks.WCF * } * ``` */ -class PublicCallableParameterFlowSource extends DataFlow::ParameterNode { +deprecated class PublicCallableParameterFlowSource extends DataFlow::ParameterNode { PublicCallableParameterFlowSource() { exists(Callable c, Parameter p | p = this.getParameter() and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll index f8240583108..07a23b36c26 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll @@ -1,218 +1,7 @@ /** - * Provides classes representing data flow sources for remote user input. + * DEPRECATED. + * + * Use `semmle.code.csharp.security.dataflow.flowsources.Remote` instead. */ -import csharp -private import semmle.code.csharp.frameworks.system.Net -private import semmle.code.csharp.frameworks.system.Web -private import semmle.code.csharp.frameworks.system.web.Http -private import semmle.code.csharp.frameworks.system.web.Mvc -private import semmle.code.csharp.frameworks.system.web.Services -private import semmle.code.csharp.frameworks.system.web.ui.WebControls -private import semmle.code.csharp.frameworks.WCF -private import semmle.code.csharp.frameworks.microsoft.Owin -private import semmle.code.csharp.frameworks.microsoft.AspNetCore - -/** A data flow source of remote user input. */ -abstract class RemoteFlowSource extends DataFlow::Node { - /** Gets a string that describes the type of this remote flow source. */ - abstract string getSourceType(); -} - -/** A data flow source of remote user input (ASP.NET). */ -abstract class AspNetRemoteFlowSource extends RemoteFlowSource { } - -/** A member containing an ASP.NET query string. */ -class AspNetQueryStringMember extends Member { - AspNetQueryStringMember() { - exists(RefType t | - t instanceof SystemWebHttpRequestClass or - t instanceof SystemNetHttpListenerRequestClass or - t instanceof SystemWebHttpRequestBaseClass - | - this = t.getProperty(getHttpRequestFlowPropertyNames()) or - this.(Field).getType() = t or - this.(Property).getType() = t or - this.(Callable).getReturnType() = t - ) - } -} - -/** - * Gets the names of the properties in `HttpRequest` classes that should propagate taint out of the - * request. - */ -private string getHttpRequestFlowPropertyNames() { - result = "QueryString" or - result = "Headers" or - result = "RawUrl" or - result = "Url" or - result = "Cookies" or - result = "Form" or - result = "Params" or - result = "Path" or - result = "PathInfo" -} - -/** A data flow source of remote user input (ASP.NET query string). */ -class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { - AspNetQueryStringRemoteFlowSource() { - exists(RefType t | - t instanceof SystemWebHttpRequestClass or - t instanceof SystemNetHttpListenerRequestClass or - t instanceof SystemWebHttpRequestBaseClass - | - // A request object can be indexed, so taint the object as well - this.getExpr().getType() = t - ) - or - this.getExpr() = any(AspNetQueryStringMember m).getAnAccess() - } - - override string getSourceType() { result = "ASP.NET query string" } -} - -/** A data flow source of remote user input (ASP.NET unvalidated request data). */ -class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, - DataFlow::ExprNode { - AspNetUnvalidatedQueryStringRemoteFlowSource() { - this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or - this.getExpr() = - any(SystemWebUnvalidatedRequestValuesBase c).getAProperty().getGetter().getACall() - } - - override string getSourceType() { result = "ASP.NET unvalidated request data" } -} - -/** A data flow source of remote user input (ASP.NET user input). */ -class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { - AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass } - - override string getSourceType() { result = "ASP.NET user input" } -} - -/** A data flow source of remote user input (WCF based web service). */ -class WcfRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { - WcfRemoteFlowSource() { exists(OperationMethod om | om.getAParameter() = this.getParameter()) } - - override string getSourceType() { result = "web service input" } -} - -/** A data flow source of remote user input (ASP.NET web service). */ -class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { - AspNetServiceRemoteFlowSource() { - exists(Method m | - m.getAParameter() = this.getParameter() and - m.getAnAttribute().getType() instanceof SystemWebServicesWebMethodAttributeClass - ) - } - - override string getSourceType() { result = "ASP.NET web service input" } -} - -/** A data flow source of remote user input (ASP.NET request message). */ -class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { - SystemNetHttpRequestMessageRemoteFlowSource() { - getType() instanceof SystemWebHttpRequestMessageClass - } - - override string getSourceType() { result = "ASP.NET request message" } -} - -/** - * A data flow source of remote user input (Microsoft Owin, a query, request, - * or path string). - */ -class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode { - MicrosoftOwinStringFlowSource() { - this.getExpr() = any(MicrosoftOwinString owinString).getValueProperty().getGetter().getACall() - } - - override string getSourceType() { result = "Microsoft Owin request or query string" } -} - -/** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */ -class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { - MicrosoftOwinRequestRemoteFlowSource() { - exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest | - this.getExpr() = p.getGetter().getACall() - | - p = owinRequest.getAcceptProperty() or - p = owinRequest.getBodyProperty() or - p = owinRequest.getCacheControlProperty() or - p = owinRequest.getContentTypeProperty() or - p = owinRequest.getContextProperty() or - p = owinRequest.getCookiesProperty() or - p = owinRequest.getHeadersProperty() or - p = owinRequest.getHostProperty() or - p = owinRequest.getMediaTypeProperty() or - p = owinRequest.getMethodProperty() or - p = owinRequest.getPathProperty() or - p = owinRequest.getPathBaseProperty() or - p = owinRequest.getQueryProperty() or - p = owinRequest.getQueryStringProperty() or - p = owinRequest.getRemoteIpAddressProperty() or - p = owinRequest.getSchemeProperty() or - p = owinRequest.getURIProperty() - ) - } - - override string getSourceType() { result = "Microsoft Owin request" } -} - -/** A parameter to an Mvc controller action method, viewed as a source of remote user input. */ -class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { - ActionMethodParameter() { - exists(Parameter p | - p = this.getParameter() and - p.fromSource() - | - p = any(Controller c).getAnActionMethod().getAParameter() or - p = any(ApiController c).getAnActionMethod().getAParameter() - ) - } - - override string getSourceType() { result = "ASP.NET MVC action method parameter" } -} - -/** A data flow source of remote user input (ASP.NET Core). */ -abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { } - -/** A data flow source of remote user input (ASP.NET query collection). */ -class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode { - AspNetCoreQueryRemoteFlowSource() { - exists(ValueOrRefType t | - t instanceof MicrosoftAspNetCoreHttpHttpRequest or - t instanceof MicrosoftAspNetCoreHttpQueryCollection or - t instanceof MicrosoftAspNetCoreHttpQueryString - | - this.getExpr().(Call).getTarget().getDeclaringType() = t or - this.asExpr().(Access).getTarget().getDeclaringType() = t - ) - or - exists(Call c | - c - .getTarget() - .getDeclaringType() - .hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and - c.getTarget().getName() = "TryGetValue" and - this.asExpr() = c.getArgumentForName("value") - ) - } - - override string getSourceType() { result = "ASP.NET Core query string" } -} - -/** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */ -class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { - AspNetCoreActionMethodParameter() { - exists(Parameter p | - p = this.getParameter() and - p.fromSource() - | - p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter() - ) - } - - override string getSourceType() { result = "ASP.NET Core MVC action method parameter" } -} +import semmle.code.csharp.security.dataflow.flowsources.Remote diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll index 8eff8c88e3f..a0ce6d9d1ae 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll @@ -5,10 +5,10 @@ import csharp module CleartextStorage { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.security.SensitiveActions - import semmle.code.csharp.security.sinks.ExternalLocationSink + import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink /** * A data flow source for cleartext storage of sensitive information. diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll index 3c168463d9d..d58d851b7c8 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll @@ -5,8 +5,8 @@ import csharp module CodeInjection { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.dataflow.flowsources.Local + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.frameworks.system.codedom.Compiler import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll index 01d6c01fd2b..7d2a49784e1 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll @@ -5,7 +5,7 @@ import csharp module CommandInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Diagnostics import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll index 18c725d273e..0694b27f985 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll @@ -8,7 +8,7 @@ import csharp module UserControlledBypassOfSensitiveMethod { import semmle.code.csharp.controlflow.Guards import semmle.code.csharp.controlflow.BasicBlocks - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.security.SensitiveActions diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll index 45d5794dca6..19866738341 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll @@ -5,8 +5,8 @@ import csharp module ExposureOfPrivateInformation { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.security.sinks.ExternalLocationSink + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink import semmle.code.csharp.security.PrivateData /** diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll index 329e001236f..50681f9721c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll @@ -6,7 +6,7 @@ import csharp module LDAPInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.DirectoryServices import semmle.code.csharp.frameworks.system.directoryservices.Protocols import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll index 3460362cf99..400b1ac8763 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll @@ -5,11 +5,11 @@ import csharp module LogForging { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.Sanitizers - import semmle.code.csharp.security.sinks.ExternalLocationSink + import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink /** * A data flow source for untrusted user input used in log entries. diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll index 28b8350a200..ba5ee7147d3 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll @@ -6,7 +6,7 @@ import csharp module MissingXMLValidation { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Xml import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll index bb40b62a0be..28c5c79e0af 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll @@ -7,7 +7,7 @@ import csharp module ReDoS { private import semmle.code.csharp.dataflow.DataFlow2 - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll index 51f8605c1af..2edfbc4ab7c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll @@ -6,7 +6,7 @@ import csharp module RegexInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll index 6ae49c6f7d5..236fe62aa2c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll @@ -5,8 +5,8 @@ import csharp module ResourceInjection { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.dataflow.flowsources.Local + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.frameworks.system.Data import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll index cb393e00179..21c2628aa62 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll @@ -5,8 +5,8 @@ import csharp module SqlInjection { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.dataflow.flowsources.Local + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.frameworks.Sql import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll index 78a0ca2c3bf..df59f0a4793 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll @@ -7,7 +7,7 @@ import csharp module TaintedPath { import semmle.code.csharp.controlflow.Guards - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.IO import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 57b3a78485b..0943774d8cd 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -6,7 +6,7 @@ import csharp module UnsafeDeserialization { - private import semmle.code.csharp.dataflow.flowsources.Remote + private import semmle.code.csharp.security.dataflow.flowsources.Remote private import semmle.code.csharp.serialization.Deserializers /** diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll index ff501a1c096..2008e62c60d 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll @@ -5,7 +5,7 @@ import csharp module UrlRedirect { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.controlflow.Guards import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.Mvc diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll index 67c5cb552f5..425fd6b4019 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll @@ -5,7 +5,7 @@ import csharp module XMLEntityInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.xml.InsecureXML diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll index e2ef4797dfe..7c84561cf44 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll @@ -5,7 +5,7 @@ import csharp module XPathInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.xml.XPath import semmle.code.csharp.frameworks.system.Xml import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll index 513b0b89f00..b8196d3c2d7 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll @@ -6,7 +6,7 @@ import csharp module XSS { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.microsoft.AspNetCore import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.frameworks.system.Web diff --git a/csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll similarity index 100% rename from csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Local.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Local.qll similarity index 100% rename from csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Local.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Local.qll diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Remote.qll new file mode 100644 index 00000000000..f8240583108 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Remote.qll @@ -0,0 +1,218 @@ +/** + * Provides classes representing data flow sources for remote user input. + */ + +import csharp +private import semmle.code.csharp.frameworks.system.Net +private import semmle.code.csharp.frameworks.system.Web +private import semmle.code.csharp.frameworks.system.web.Http +private import semmle.code.csharp.frameworks.system.web.Mvc +private import semmle.code.csharp.frameworks.system.web.Services +private import semmle.code.csharp.frameworks.system.web.ui.WebControls +private import semmle.code.csharp.frameworks.WCF +private import semmle.code.csharp.frameworks.microsoft.Owin +private import semmle.code.csharp.frameworks.microsoft.AspNetCore + +/** A data flow source of remote user input. */ +abstract class RemoteFlowSource extends DataFlow::Node { + /** Gets a string that describes the type of this remote flow source. */ + abstract string getSourceType(); +} + +/** A data flow source of remote user input (ASP.NET). */ +abstract class AspNetRemoteFlowSource extends RemoteFlowSource { } + +/** A member containing an ASP.NET query string. */ +class AspNetQueryStringMember extends Member { + AspNetQueryStringMember() { + exists(RefType t | + t instanceof SystemWebHttpRequestClass or + t instanceof SystemNetHttpListenerRequestClass or + t instanceof SystemWebHttpRequestBaseClass + | + this = t.getProperty(getHttpRequestFlowPropertyNames()) or + this.(Field).getType() = t or + this.(Property).getType() = t or + this.(Callable).getReturnType() = t + ) + } +} + +/** + * Gets the names of the properties in `HttpRequest` classes that should propagate taint out of the + * request. + */ +private string getHttpRequestFlowPropertyNames() { + result = "QueryString" or + result = "Headers" or + result = "RawUrl" or + result = "Url" or + result = "Cookies" or + result = "Form" or + result = "Params" or + result = "Path" or + result = "PathInfo" +} + +/** A data flow source of remote user input (ASP.NET query string). */ +class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { + AspNetQueryStringRemoteFlowSource() { + exists(RefType t | + t instanceof SystemWebHttpRequestClass or + t instanceof SystemNetHttpListenerRequestClass or + t instanceof SystemWebHttpRequestBaseClass + | + // A request object can be indexed, so taint the object as well + this.getExpr().getType() = t + ) + or + this.getExpr() = any(AspNetQueryStringMember m).getAnAccess() + } + + override string getSourceType() { result = "ASP.NET query string" } +} + +/** A data flow source of remote user input (ASP.NET unvalidated request data). */ +class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, + DataFlow::ExprNode { + AspNetUnvalidatedQueryStringRemoteFlowSource() { + this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or + this.getExpr() = + any(SystemWebUnvalidatedRequestValuesBase c).getAProperty().getGetter().getACall() + } + + override string getSourceType() { result = "ASP.NET unvalidated request data" } +} + +/** A data flow source of remote user input (ASP.NET user input). */ +class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { + AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass } + + override string getSourceType() { result = "ASP.NET user input" } +} + +/** A data flow source of remote user input (WCF based web service). */ +class WcfRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { + WcfRemoteFlowSource() { exists(OperationMethod om | om.getAParameter() = this.getParameter()) } + + override string getSourceType() { result = "web service input" } +} + +/** A data flow source of remote user input (ASP.NET web service). */ +class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { + AspNetServiceRemoteFlowSource() { + exists(Method m | + m.getAParameter() = this.getParameter() and + m.getAnAttribute().getType() instanceof SystemWebServicesWebMethodAttributeClass + ) + } + + override string getSourceType() { result = "ASP.NET web service input" } +} + +/** A data flow source of remote user input (ASP.NET request message). */ +class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { + SystemNetHttpRequestMessageRemoteFlowSource() { + getType() instanceof SystemWebHttpRequestMessageClass + } + + override string getSourceType() { result = "ASP.NET request message" } +} + +/** + * A data flow source of remote user input (Microsoft Owin, a query, request, + * or path string). + */ +class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode { + MicrosoftOwinStringFlowSource() { + this.getExpr() = any(MicrosoftOwinString owinString).getValueProperty().getGetter().getACall() + } + + override string getSourceType() { result = "Microsoft Owin request or query string" } +} + +/** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */ +class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { + MicrosoftOwinRequestRemoteFlowSource() { + exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest | + this.getExpr() = p.getGetter().getACall() + | + p = owinRequest.getAcceptProperty() or + p = owinRequest.getBodyProperty() or + p = owinRequest.getCacheControlProperty() or + p = owinRequest.getContentTypeProperty() or + p = owinRequest.getContextProperty() or + p = owinRequest.getCookiesProperty() or + p = owinRequest.getHeadersProperty() or + p = owinRequest.getHostProperty() or + p = owinRequest.getMediaTypeProperty() or + p = owinRequest.getMethodProperty() or + p = owinRequest.getPathProperty() or + p = owinRequest.getPathBaseProperty() or + p = owinRequest.getQueryProperty() or + p = owinRequest.getQueryStringProperty() or + p = owinRequest.getRemoteIpAddressProperty() or + p = owinRequest.getSchemeProperty() or + p = owinRequest.getURIProperty() + ) + } + + override string getSourceType() { result = "Microsoft Owin request" } +} + +/** A parameter to an Mvc controller action method, viewed as a source of remote user input. */ +class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { + ActionMethodParameter() { + exists(Parameter p | + p = this.getParameter() and + p.fromSource() + | + p = any(Controller c).getAnActionMethod().getAParameter() or + p = any(ApiController c).getAnActionMethod().getAParameter() + ) + } + + override string getSourceType() { result = "ASP.NET MVC action method parameter" } +} + +/** A data flow source of remote user input (ASP.NET Core). */ +abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { } + +/** A data flow source of remote user input (ASP.NET query collection). */ +class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode { + AspNetCoreQueryRemoteFlowSource() { + exists(ValueOrRefType t | + t instanceof MicrosoftAspNetCoreHttpHttpRequest or + t instanceof MicrosoftAspNetCoreHttpQueryCollection or + t instanceof MicrosoftAspNetCoreHttpQueryString + | + this.getExpr().(Call).getTarget().getDeclaringType() = t or + this.asExpr().(Access).getTarget().getDeclaringType() = t + ) + or + exists(Call c | + c + .getTarget() + .getDeclaringType() + .hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and + c.getTarget().getName() = "TryGetValue" and + this.asExpr() = c.getArgumentForName("value") + ) + } + + override string getSourceType() { result = "ASP.NET Core query string" } +} + +/** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */ +class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { + AspNetCoreActionMethodParameter() { + exists(Parameter p | + p = this.getParameter() and + p.fromSource() + | + p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter() + ) + } + + override string getSourceType() { result = "ASP.NET Core MVC action method parameter" } +} diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs deleted file mode 100644 index d4d8016974a..00000000000 --- a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Specialized; - -class PublicCallableParameterFlowSource -{ - public void M1(string x, out string y, ref string z) - { - y = x; - y = z; - } - - void M2(string x, out string y, ref string z) - { - y = x; - y = z; - } -} diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected deleted file mode 100644 index 8d80e68a16c..00000000000 --- a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected +++ /dev/null @@ -1,2 +0,0 @@ -| PublicCallableParameterFlowSource.cs:6:27:6:27 | x | -| PublicCallableParameterFlowSource.cs:6:55:6:55 | z | diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql deleted file mode 100644 index b5a6460a7ca..00000000000 --- a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql +++ /dev/null @@ -1,5 +0,0 @@ -import semmle.code.csharp.dataflow.flowsources.PublicCallableParameter - -from PublicCallableParameterFlowSource source -where source.getParameter().fromSource() -select source diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql b/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql index 4015799bd1a..29281ffba56 100644 --- a/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql +++ b/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql @@ -1,4 +1,4 @@ -import semmle.code.csharp.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Remote from RemoteFlowSource source select source, source.getSourceType() From 142737dc61ae31f31264fa9f21fb966313e7954d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 25 Mar 2020 13:48:34 +0100 Subject: [PATCH 135/459] C#: Move `HtmlSink`s from `XSS.qll` into separate file --- .../CWE-838/InappropriateEncoding.ql | 4 +- .../code/csharp/security/dataflow/XSS.qll | 224 ++---------------- .../security/dataflow/flowsinks/Html.qll | 206 ++++++++++++++++ 3 files changed, 225 insertions(+), 209 deletions(-) create mode 100644 csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll diff --git a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql index 88a5c3da4ed..88a0b970a7a 100644 --- a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql +++ b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql @@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.UI import semmle.code.csharp.security.dataflow.SqlInjection -import semmle.code.csharp.security.dataflow.XSS +import semmle.code.csharp.security.dataflow.flowsinks.Html import semmle.code.csharp.security.dataflow.UrlRedirect import semmle.code.csharp.security.Sanitizers import semmle.code.csharp.dataflow.DataFlow2::DataFlow2 @@ -114,7 +114,7 @@ module EncodingConfigurations { override string getKind() { result = "HTML expression" } - override predicate requiresEncoding(Node n) { n instanceof XSS::HtmlSink } + override predicate requiresEncoding(Node n) { n instanceof HtmlSink } override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll index b8196d3c2d7..84ed897256f 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll @@ -6,17 +6,13 @@ import csharp module XSS { - import semmle.code.csharp.security.dataflow.flowsources.Remote - import semmle.code.csharp.frameworks.microsoft.AspNetCore + import semmle.code.asp.AspNet import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.frameworks.system.Web - import semmle.code.csharp.frameworks.system.web.Mvc - import semmle.code.csharp.frameworks.system.web.WebPages import semmle.code.csharp.frameworks.system.web.UI - import semmle.code.csharp.frameworks.system.web.ui.WebControls - import semmle.code.csharp.frameworks.system.windows.Forms import semmle.code.csharp.security.Sanitizers - import semmle.code.asp.AspNet + import semmle.code.csharp.security.dataflow.flowsinks.Html + import semmle.code.csharp.security.dataflow.flowsources.Remote /** * Holds if there is tainted flow from `source` to `sink` that may lead to a @@ -166,78 +162,21 @@ module XSS { UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr } } - /** A sink where the value of the expression may be rendered as HTML. */ - abstract class HtmlSink extends DataFlow::Node { } + private class HtmlSinkSink extends Sink { + HtmlSinkSink() { this instanceof HtmlSink } - /** - * An expression that is used as an argument to an XSS sink method on - * `HttpResponse`. - */ - private class HttpResponseSink extends Sink, HtmlSink { - HttpResponseSink() { - exists(Method m, SystemWebHttpResponseClass responseClass | - m = responseClass.getAWriteMethod() or - m = responseClass.getAWriteFileMethod() or - m = responseClass.getATransmitFileMethod() or - m = responseClass.getABinaryWriteMethod() - | - // Calls to these methods, or overrides of them - this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument() - ) - } - } - - /** - * An expression that is used as an argument to an XSS sink method on - * `HtmlTextWriter`. - */ - private class HtmlTextWriterSink extends Sink, HtmlSink { - HtmlTextWriterSink() { - exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos | - paramPos = 0 and - ( - m = writeClass.getAWriteMethod() or - m = writeClass.getAWriteLineMethod() or - m = writeClass.getAWriteLineNoTabsMethod() or - m = writeClass.getAWriteBeginTagMethod() or - m = writeClass.getAWriteAttributeMethod() - ) - or - // The second parameter to the `WriteAttribute` method is the attribute value, which we - // should only consider as tainted if the call does not ask for the attribute value to be - // encoded using the final parameter. - m = writeClass.getAWriteAttributeMethod() and - paramPos = 1 and - not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true - | - c = m.getACall() and - this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos)) - ) - } - } - - /** - * An expression that is used as an argument to an XSS sink method on - * `AttributeCollection`. - */ - private class AttributeCollectionSink extends Sink, HtmlSink { - AttributeCollectionSink() { - exists(SystemWebUIAttributeCollectionClass ac, Parameter p | - p = ac.getAddMethod().getParameter(1) or - p = ac.getItemProperty().getSetter().getParameter(0) - | - this.getExpr() = p.getAnAssignedArgument() - ) - } - } - - /** - * An expression that is used as the second argument `HtmlElement.SetAttribute`. - */ - private class SetAttributeSink extends Sink, HtmlSink { - SetAttributeSink() { - this.getExpr() = - any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1) + override string explanation() { + this instanceof WebPageWriteLiteralSink and + result = "System.Web.WebPages.WebPage.WriteLiteral() method" + or + this instanceof WebPageWriteLiteralToSink and + result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" + or + this instanceof MicrosoftAspNetCoreMvcHtmlHelperRawSink and + result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method" + or + this instanceof MicrosoftAspNetRazorPageWriteLiteralSink and + result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method" } } @@ -285,31 +224,6 @@ module XSS { } } - /** - * An expression that is used as an argument to an XSS sink setter, on - * a class within the `System.Web.UI` namespace. - */ - private class SystemWebSetterHtmlSink extends Sink, HtmlSink { - SystemWebSetterHtmlSink() { - exists(Property p, string name, ValueOrRefType declaringType | - declaringType = p.getDeclaringType() and - any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and - this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and - p.hasName(name) - | - name = "Caption" and - (declaringType.hasName("Calendar") or declaringType.hasName("Table")) - or - name = "InnerHtml" - ) - or - exists(SystemWebUIWebControlsLabelClass c | - // Unlike `Text` properties of other web controls, `Label.Text` is not automatically HTML encoded - this.getExpr() = c.getTextProperty().getSetter().getParameter(0).getAnAssignedArgument() - ) - } - } - /** * An expression that is used as an argument to an XSS sink setter, on * a class within the `System.Web.UI` namespace. @@ -345,16 +259,6 @@ module XSS { } } - /** - * An expression that is used as an argument to `HtmlHelper.Raw`, typically in - * a `.cshtml` file. - */ - private class SystemWebMvcHtmlHelperRawSink extends Sink, HtmlSink { - SystemWebMvcHtmlHelperRawSink() { - this.getExpr() = any(SystemWebMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() - } - } - /** * Gets a member which is accessed by the given `AspInlineCode`. * The code body must consist only of an access to the member, possibly with qualified @@ -493,31 +397,6 @@ module XSS { } } - /** An expression that is returned from a `ToHtmlString` method. */ - private class ToHtmlString extends Sink, HtmlSink { - ToHtmlString() { - exists(Method toHtmlString | - toHtmlString = - any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and - toHtmlString.canReturn(this.getExpr()) - ) - } - } - - /** - * An expression passed to the constructor of an `HtmlString` or a `MvcHtmlString`. - */ - private class HtmlString extends Sink, HtmlSink { - HtmlString() { - exists(Class c | - c = any(SystemWebMvcMvcHtmlString m) or - c = any(SystemWebHtmlString m) - | - this.getExpr() = c.getAConstructor().getACall().getAnArgument() - ) - } - } - /** * An expression passed as the `content` argument to the constructor of `StringContent`. */ @@ -529,75 +408,6 @@ module XSS { ).getArgumentForName("content") } } - - /** - * An expression that is used as an argument to `Page.WriteLiteral`, typically in - * a `.cshtml` file. - */ - class WebPageWriteLiteralSink extends Sink, HtmlSink { - WebPageWriteLiteralSink() { - this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument() - } - - override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteral() method" } - } - - /** - * An expression that is used as an argument to `Page.WriteLiteralTo`, typically in - * a `.cshtml` file. - */ - class WebPageWriteLiteralToSink extends Sink, HtmlSink { - WebPageWriteLiteralToSink() { - this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument() - } - - override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" } - } - - abstract class AspNetCoreSink extends Sink, HtmlSink { } - - /** - * An expression that is used as an argument to `HtmlHelper.Raw`, typically in - * a `.cshtml` file. - */ - class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreSink { - MicrosoftAspNetCoreMvcHtmlHelperRawSink() { - this.getExpr() = - any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() - } - - override string explanation() { - result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method" - } - } - - /** - * An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in - * a `.cshtml` file. - */ - class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreSink { - MicrosoftAspNetRazorPageWriteLiteralSink() { - this.getExpr() = - any(MicrosoftAspNetCoreMvcRazorPageBase h) - .getWriteLiteralMethod() - .getACall() - .getAnArgument() - } - - override string explanation() { - result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method" - } - } - - /** `HtmlString` that may be rendered as is need to have sanitized value. */ - class MicrosoftAspNetHtmlStringSink extends AspNetCoreSink { - MicrosoftAspNetHtmlStringSink() { - exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s | - c.getTarget() = s.getAConstructor() and - this.asExpr() = c.getAnArgument() - ) - } - } } private Type getMemberType(Member m) { diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll new file mode 100644 index 00000000000..7bd21825880 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll @@ -0,0 +1,206 @@ +/** + * Provides classes representing HTML data flow sinks. + */ + +import csharp +private import semmle.code.csharp.frameworks.microsoft.AspNetCore +private import semmle.code.csharp.frameworks.system.Net +private import semmle.code.csharp.frameworks.system.Web +private import semmle.code.csharp.frameworks.system.web.Mvc +private import semmle.code.csharp.frameworks.system.web.WebPages +private import semmle.code.csharp.frameworks.system.web.UI +private import semmle.code.csharp.frameworks.system.web.ui.WebControls +private import semmle.code.csharp.frameworks.system.windows.Forms +private import semmle.code.csharp.security.dataflow.flowsources.Remote +private import semmle.code.asp.AspNet + +/** + * A sink where the value of the expression may be rendered as HTML, + * without implicit HTML encoding. + */ +abstract class HtmlSink extends DataFlow::ExprNode { } + +/** + * An expression that is used as an argument to an HTML sink method on + * `HttpResponse`. + */ +class HttpResponseSink extends HtmlSink { + HttpResponseSink() { + exists(Method m, SystemWebHttpResponseClass responseClass | + m = responseClass.getAWriteMethod() or + m = responseClass.getAWriteFileMethod() or + m = responseClass.getATransmitFileMethod() or + m = responseClass.getABinaryWriteMethod() + | + // Calls to these methods, or overrides of them + this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument() + ) + } +} + +/** + * An expression that is used as an argument to an HTML sink method on + * `HtmlTextWriter`. + */ +class HtmlTextWriterSink extends HtmlSink { + HtmlTextWriterSink() { + exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos | + paramPos = 0 and + ( + m = writeClass.getAWriteMethod() or + m = writeClass.getAWriteLineMethod() or + m = writeClass.getAWriteLineNoTabsMethod() or + m = writeClass.getAWriteBeginTagMethod() or + m = writeClass.getAWriteAttributeMethod() + ) + or + // The second parameter to the `WriteAttribute` method is the attribute value, which we + // should only consider as tainted if the call does not ask for the attribute value to be + // encoded using the final parameter. + m = writeClass.getAWriteAttributeMethod() and + paramPos = 1 and + not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true + | + c = m.getACall() and + this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos)) + ) + } +} + +/** + * An expression that is used as an argument to an HTML sink method on + * `AttributeCollection`. + */ +class AttributeCollectionSink extends HtmlSink { + AttributeCollectionSink() { + exists(SystemWebUIAttributeCollectionClass ac, Parameter p | + p = ac.getAddMethod().getParameter(1) or + p = ac.getItemProperty().getSetter().getParameter(0) + | + this.getExpr() = p.getAnAssignedArgument() + ) + } +} + +/** + * An expression that is used as the second argument `HtmlElement.SetAttribute`. + */ +class SetAttributeSink extends HtmlSink { + SetAttributeSink() { + this.getExpr() = + any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1) + } +} + +/** + * An expression that is used as an argument to an HTML sink setter, on + * a class within the `System.Web.UI` namespace. + */ +class SystemWebSetterHtmlSink extends HtmlSink { + SystemWebSetterHtmlSink() { + exists(Property p, string name, ValueOrRefType declaringType | + declaringType = p.getDeclaringType() and + any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and + this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and + p.hasName(name) + | + name = "Caption" and + (declaringType.hasName("Calendar") or declaringType.hasName("Table")) + or + name = "InnerHtml" + ) + or + exists(SystemWebUIWebControlsLabelClass c | + // Unlike `Text` properties of other web controls, `Label.Text` is not automatically HTML encoded + this.getExpr() = c.getTextProperty().getSetter().getParameter(0).getAnAssignedArgument() + ) + } +} + +/** + * An expression that is used as an argument to `HtmlHelper.Raw`, typically in + * a `.cshtml` file. + */ +class SystemWebMvcHtmlHelperRawSink extends HtmlSink { + SystemWebMvcHtmlHelperRawSink() { + this.getExpr() = any(SystemWebMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() + } +} + +/** An expression that is returned from a `ToHtmlString` method. */ +class ToHtmlString extends HtmlSink { + ToHtmlString() { + exists(Method toHtmlString | + toHtmlString = any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and + toHtmlString.canReturn(this.getExpr()) + ) + } +} + +/** + * An expression passed to the constructor of an `HtmlString` or a `MvcHtmlString`. + */ +class HtmlString extends HtmlSink { + HtmlString() { + exists(Class c | + c = any(SystemWebMvcMvcHtmlString m) or + c = any(SystemWebHtmlString m) + | + this.getExpr() = c.getAConstructor().getACall().getAnArgument() + ) + } +} + +/** + * An expression that is used as an argument to `Page.WriteLiteral`, typically in + * a `.cshtml` file. + */ +class WebPageWriteLiteralSink extends HtmlSink { + WebPageWriteLiteralSink() { + this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument() + } +} + +/** + * An expression that is used as an argument to `Page.WriteLiteralTo`, typically in + * a `.cshtml` file. + */ +class WebPageWriteLiteralToSink extends HtmlSink { + WebPageWriteLiteralToSink() { + this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument() + } +} + +abstract class AspNetCoreHtmlSink extends HtmlSink { } + +/** + * An expression that is used as an argument to `HtmlHelper.Raw`, typically in + * a `.cshtml` file. + */ +class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreHtmlSink { + MicrosoftAspNetCoreMvcHtmlHelperRawSink() { + this.getExpr() = + any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() + } +} + +/** + * An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in + * a `.cshtml` file. + */ +class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreHtmlSink { + MicrosoftAspNetRazorPageWriteLiteralSink() { + this.getExpr() = + any(MicrosoftAspNetCoreMvcRazorPageBase h).getWriteLiteralMethod().getACall().getAnArgument() + } +} + +/** `HtmlString` that may be rendered as is need to have sanitized value. */ +class MicrosoftAspNetHtmlStringSink extends AspNetCoreHtmlSink { + MicrosoftAspNetHtmlStringSink() { + exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s | + c.getTarget() = s.getAConstructor() and + this.asExpr() = c.getAnArgument() + ) + } +} From 54677189de5c04d841c494573a405109d8ae63c0 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 25 Mar 2020 14:29:46 +0100 Subject: [PATCH 136/459] C#: Introduce `RemoteFlowSink` class --- .../CWE-201/ExposureInTransmittedData.ql | 9 ++---- .../CWE-209/ExceptionInformationExposure.ql | 4 +-- .../code/csharp/security/dataflow/XSS.qll | 6 +++- .../dataflow/{ => flowsinks}/Email.qll | 3 +- .../flowsinks/ExternalLocationSink.qll | 3 +- .../security/dataflow/flowsinks/Html.qll | 5 +-- .../security/dataflow/flowsinks/Remote.qll | 31 +++++++++++++++++++ .../CWE-209/ExceptionInformationExposure.cs | 6 ++-- .../ExceptionInformationExposure.expected | 6 ++++ 9 files changed, 56 insertions(+), 17 deletions(-) rename csharp/ql/src/semmle/code/csharp/security/dataflow/{ => flowsinks}/Email.qll (91%) create mode 100644 csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll diff --git a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql index 4419a4f1312..b8b18c6b56d 100644 --- a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql +++ b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql @@ -11,8 +11,7 @@ import csharp import semmle.code.csharp.security.SensitiveActions -import semmle.code.csharp.security.dataflow.XSS -import semmle.code.csharp.security.dataflow.Email +import semmle.code.csharp.security.dataflow.flowsinks.Remote import semmle.code.csharp.frameworks.system.data.Common import semmle.code.csharp.frameworks.System import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -42,11 +41,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { - sink instanceof XSS::Sink - or - sink instanceof Email::Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof RemoteFlowSink } } from TaintTrackingConfiguration configuration, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql index 8cebb2601c4..d9db652c8d8 100644 --- a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql +++ b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql @@ -14,7 +14,7 @@ import csharp import semmle.code.csharp.frameworks.System -import semmle.code.csharp.security.dataflow.XSS +import semmle.code.csharp.security.dataflow.flowsinks.Remote import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph /** @@ -46,7 +46,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { sink instanceof XSS::Sink } + override predicate isSink(DataFlow::Node sink) { sink instanceof RemoteFlowSink } override predicate isSanitizer(DataFlow::Node sanitizer) { // Do not flow through Message diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll index 84ed897256f..635c59363f5 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll @@ -12,6 +12,7 @@ module XSS { import semmle.code.csharp.frameworks.system.web.UI import semmle.code.csharp.security.Sanitizers import semmle.code.csharp.security.dataflow.flowsinks.Html + import semmle.code.csharp.security.dataflow.flowsinks.Remote import semmle.code.csharp.security.dataflow.flowsources.Remote /** @@ -108,8 +109,11 @@ module XSS { /** * A data flow sink for cross-site scripting (XSS) vulnerabilities. + * + * Any XSS sink is also a remote flow sink, so this class contributes + * to the abstract class `RemoteFlowSink`. */ - abstract class Sink extends DataFlow::ExprNode { + abstract class Sink extends DataFlow::ExprNode, RemoteFlowSink { string explanation() { none() } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll similarity index 91% rename from csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll index b86fa4822ae..e4552d77cae 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll @@ -1,11 +1,12 @@ /** Provides data flow sinks for sending email. */ import csharp +private import Remote private import semmle.code.csharp.frameworks.system.net.Mail module Email { /** A data flow sink for sending email. */ - abstract class Sink extends DataFlow::ExprNode { } + abstract class Sink extends DataFlow::ExprNode, RemoteFlowSink { } /** A data flow sink for sending email via `System.Net.Mail.MailMessage`. */ class MailMessageSink extends Sink { diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll index 6cd1a5cb269..25a50f3733c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll @@ -3,6 +3,7 @@ */ import csharp +private import Remote private import semmle.code.csharp.commons.Loggers private import semmle.code.csharp.frameworks.system.Web @@ -45,7 +46,7 @@ class TraceMessageSink extends ExternalLocationSink { /** * An expression set as a value on a cookie instance. */ -class CookieStorageSink extends ExternalLocationSink { +class CookieStorageSink extends ExternalLocationSink, RemoteFlowSink { CookieStorageSink() { exists(Expr e | e = this.getExpr() | e = any(SystemWebHttpCookie cookie).getAConstructor().getACall().getArgumentForName("value") diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll index 7bd21825880..a507ef0663b 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll @@ -3,6 +3,7 @@ */ import csharp +private import Remote private import semmle.code.csharp.frameworks.microsoft.AspNetCore private import semmle.code.csharp.frameworks.system.Net private import semmle.code.csharp.frameworks.system.Web @@ -18,7 +19,7 @@ private import semmle.code.asp.AspNet * A sink where the value of the expression may be rendered as HTML, * without implicit HTML encoding. */ -abstract class HtmlSink extends DataFlow::ExprNode { } +abstract class HtmlSink extends DataFlow::ExprNode, RemoteFlowSink { } /** * An expression that is used as an argument to an HTML sink method on @@ -101,7 +102,7 @@ class SystemWebSetterHtmlSink extends HtmlSink { exists(Property p, string name, ValueOrRefType declaringType | declaringType = p.getDeclaringType() and any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and - this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and + this.getExpr() = p.getAnAssignedValue() and p.hasName(name) | name = "Caption" and diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll new file mode 100644 index 00000000000..19451b14194 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll @@ -0,0 +1,31 @@ +/** + * Provides classes representing data flow sinks for remote user output. + */ + +import csharp +private import Email +private import ExternalLocationSink +private import Html +private import semmle.code.csharp.security.dataflow.XSS +private import semmle.code.csharp.frameworks.system.web.UI + +/** A data flow sink of remote user output. */ +abstract class RemoteFlowSink extends DataFlow::Node { } + +/** + * A value written to the `[Inner]Text` property of an object defined in the + * `System.Web.UI` namespace. + */ +class SystemWebUIText extends RemoteFlowSink { + SystemWebUIText() { + exists(Property p, string name | + p.getDeclaringType().getNamespace().getParentNamespace*() instanceof SystemWebUINamespace and + this.asExpr() = p.getAnAssignedValue() and + p.hasName(name) + | + name = "Text" + or + name = "InnerText" + ) + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs index 7de4fd18c75..c0d56d1337e 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs @@ -38,9 +38,9 @@ public class StackTraceHandler : IHttpHandler log("Exception occurred", ex); ctx.Response.Write("Exception occurred"); - textBox.Text = ex.InnerException.StackTrace; // BAD (false negative) - textBox.Text = ex.StackTrace; // BAD (false negative) - textBox.Text = ex.ToString(); // BAD (false negative) + textBox.Text = ex.InnerException.StackTrace; // BAD + textBox.Text = ex.StackTrace; // BAD + textBox.Text = ex.ToString(); // BAD textBox.Text = ex.Message; // GOOD return; } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected index 34c64432966..492a61dd038 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected @@ -5,10 +5,16 @@ nodes | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | semmle.label | call to method ToString | | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | semmle.label | access to local variable ex | | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | semmle.label | access to property StackTrace | +| ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | semmle.label | access to property StackTrace | +| ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | semmle.label | access to property StackTrace | +| ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | semmle.label | call to method ToString | | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | semmle.label | call to method ToString | #select | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | call to method ToString | | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex | access to local variable ex : Exception | | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | access to local variable ex | | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | call to method ToString | | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | call to method ToString | From 95b6f6aee0ee4ded1cba5f7c936638075cd37f8f Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 25 Mar 2020 15:37:41 +0100 Subject: [PATCH 137/459] C#: Add change note --- change-notes/1.24/analysis-csharp.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/change-notes/1.24/analysis-csharp.md b/change-notes/1.24/analysis-csharp.md index 02f31b12533..057f06685cf 100644 --- a/change-notes/1.24/analysis-csharp.md +++ b/change-notes/1.24/analysis-csharp.md @@ -22,6 +22,8 @@ The following changes in version 1.24 affect C# analysis in all applications. | Dereferenced variable may be null (`cs/dereferenced-value-may-be-null`) | More results | Results are reported from parameters with a default value of `null`. | | Useless assignment to local variable (`cs/useless-assignment-to-local`) | Fewer false positive results | Results have been removed when the value assigned is an (implicitly or explicitly) cast default-like value. For example, `var s = (string)null` and `string s = default`. | | XPath injection (`cs/xml/xpath-injection`) | More results | The query now recognizes calls to methods on `System.Xml.XPath.XPathNavigator` objects. | +| Information exposure through transmitted data (`cs/sensitive-data-transmission`) | More results | The query now recognizes writes to cookies and writes to ASP.NET (`Inner`)`Text` properties as additional sinks. | +| Information exposure through an exception (`cs/information-exposure-through-exception`) | More results | The query now recognizes writes to cookies, writes to ASP.NET (`Inner`)`Text` properties, and email contents as additional sinks. | ## Removal of old queries From 9a78d38df01f0b93abb383fa7d3ee719ed2931ce Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Mar 2020 20:00:34 +0100 Subject: [PATCH 138/459] add a new LoadStoreStep as a StepSummary for TypeTracking --- .../ql/src/semmle/javascript/dataflow/TypeTracking.qll | 6 +++++- .../src/semmle/javascript/dataflow/internal/StepSummary.qll | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll index ba49ac93dd5..4edd1451a5b 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll @@ -44,7 +44,7 @@ private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyNa */ class TypeTracker extends TTypeTracker { Boolean hasCall; - string prop; + OptionalPropertyName prop; TypeTracker() { this = MkTypeTracker(hasCall, prop) } @@ -53,6 +53,8 @@ class TypeTracker extends TTypeTracker { TypeTracker append(StepSummary step) { step = LevelStep() and result = this or + step = LoadStoreStep(prop) and result = this + or step = CallStep() and result = MkTypeTracker(true, prop) or step = ReturnStep() and hasCall = false and result = this @@ -211,6 +213,8 @@ class TypeBackTracker extends TTypeBackTracker { TypeBackTracker prepend(StepSummary step) { step = LevelStep() and result = this or + step = LoadStoreStep(prop) and result = this + or step = CallStep() and hasReturn = false and result = this or step = ReturnStep() and result = MkTypeBackTracker(true, prop) diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll index a848cd57434..25f8fb356fb 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll @@ -34,7 +34,8 @@ newtype TStepSummary = CallStep() or ReturnStep() or StoreStep(PropertyName prop) or - LoadStep(PropertyName prop) + LoadStep(PropertyName prop) or + LoadStoreStep(PropertyName prop) /** * INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead. @@ -53,6 +54,8 @@ class StepSummary extends TStepSummary { exists(string prop | this = StoreStep(prop) | result = "store " + prop) or exists(string prop | this = LoadStep(prop) | result = "load " + prop) + or + exists(string prop | this = LoadStoreStep(prop) | result = "in " + prop) } } From 00181e059b95ad4648837274ea637f76c641c254 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Mar 2020 20:01:15 +0100 Subject: [PATCH 139/459] add tests for type-tracking promises --- javascript/ql/test/library-tests/Promises/flow.qll | 5 +++++ javascript/ql/test/library-tests/Promises/promises.js | 7 +++++++ .../library-tests/frameworks/Concepts/tst-file-names.js | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/javascript/ql/test/library-tests/Promises/flow.qll b/javascript/ql/test/library-tests/Promises/flow.qll index 0b99ee9bcbd..d93f08a2ec4 100644 --- a/javascript/ql/test/library-tests/Promises/flow.qll +++ b/javascript/ql/test/library-tests/Promises/flow.qll @@ -1,4 +1,5 @@ import javascript +private import semmle.javascript.dataflow.internal.StepSummary class Configuration extends DataFlow::Configuration { Configuration() { this = "PromiseDataFlowFlowTestingConfig" } @@ -32,3 +33,7 @@ query predicate exclusiveTaintFlow(DataFlow::Node source, DataFlow::Node sink) { not any(Configuration c).hasFlow(source, sink) and any(TaintConfig c).hasFlow(source, sink) } + +query predicate typetrack(DataFlow::SourceNode succ, DataFlow::SourceNode pred, StepSummary summary) { + succ = PromiseTypeTracking::promiseStep(pred, summary) +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Promises/promises.js b/javascript/ql/test/library-tests/Promises/promises.js index f053c81a9a9..8a3d0cbc5cf 100644 --- a/javascript/ql/test/library-tests/Promises/promises.js +++ b/javascript/ql/test/library-tests/Promises/promises.js @@ -74,3 +74,10 @@ resolver.resolve(source); resolver.promise.then(val => { var sink = val }); })(); + +(function(source) { + var promise = Promise.resolve(source); + promise.then(function (val) { + var sink = val; + }); +})(); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js b/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js index 2892a82d515..7c9670dba04 100644 --- a/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js +++ b/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js @@ -45,3 +45,8 @@ var bool = globule.isMatch('**/*.js', ["foo.js"]) var map1 = globule.findMapping("foo/*.js") var map2 = globule.mapping({src: ["a.js", "b.js"]}) var map3 = globule.mapping(["foo/a.js", "foo/b.js"]) + +async function bar() { + var foo = globby(_); + var files = await foo; +} \ No newline at end of file From 1a2983fe392bd9ff07056ecf9d34a5770662d0c8 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Mar 2020 20:02:15 +0100 Subject: [PATCH 140/459] support small steps for promise tracking --- javascript/ql/src/semmle/javascript/Promises.qll | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 77ffdb47eca..f369e5d3527 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -168,7 +168,7 @@ module PromiseTypeTracking { * This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another. */ pragma[inline] - DataFlow::SourceNode promiseStep(DataFlow::SourceNode pred, StepSummary summary) { + DataFlow::Node promiseStep(DataFlow::Node pred, StepSummary summary) { exists(PromiseFlowStep step, string field | field = Promises::valueProp() | summary = LoadStep(field) and step.load(pred, result, field) @@ -189,9 +189,8 @@ module PromiseTypeTracking { DataFlow::SourceNode promiseStep( DataFlow::SourceNode pred, DataFlow::TypeTracker t, DataFlow::TypeTracker t2 ) { - exists(StepSummary summary | - result = PromiseTypeTracking::promiseStep(pred, summary) and - t = t2.append(summary) + exists(DataFlow::Node mid, StepSummary summary | pred.flowsTo(mid) and t = t2.append(summary) | + result = PromiseTypeTracking::promiseStep(mid, summary) ) } From 8f45c8fe83365773da74e8d12e14775ad379b9bc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Mar 2020 20:02:35 +0100 Subject: [PATCH 141/459] use LoadStoreStep for type-tracking promises --- javascript/ql/src/semmle/javascript/Promises.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index f369e5d3527..56025b75ffb 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -176,7 +176,7 @@ module PromiseTypeTracking { summary = StoreStep(field) and step.store(pred, result, field) or - summary = LevelStep() and + summary = LoadStoreStep(field) and step.loadStore(pred, result, field) ) } From 1cefa123156085e73c93226586bec065aac7eeb2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Mar 2020 20:02:43 +0100 Subject: [PATCH 142/459] update expected output --- .../library-tests/Promises/tests.expected | 178 ++++++++++++++++++ .../Concepts/FileNameSource.expected | 1 + 2 files changed, 179 insertions(+) diff --git a/javascript/ql/test/library-tests/Promises/tests.expected b/javascript/ql/test/library-tests/Promises/tests.expected index f4ee1263be5..4cd42537f3e 100644 --- a/javascript/ql/test/library-tests/Promises/tests.expected +++ b/javascript/ql/test/library-tests/Promises/tests.expected @@ -19,6 +19,7 @@ test_ResolvedPromiseDefinition | promises.js:53:19:53:41 | Promise ... source) | promises.js:53:35:53:40 | source | | promises.js:62:19:62:41 | Promise ... source) | promises.js:62:35:62:40 | source | | promises.js:71:5:71:27 | Promise ... source) | promises.js:71:21:71:26 | source | +| promises.js:79:19:79:41 | Promise ... source) | promises.js:79:35:79:40 | source | test_PromiseDefinition_getARejectHandler | flow.js:26:2:26:49 | new Pro ... ource)) | flow.js:26:69:26:80 | y => sink(y) | | flow.js:32:2:32:49 | new Pro ... ource)) | flow.js:32:57:32:68 | x => sink(x) | @@ -220,3 +221,180 @@ flow | flow.js:2:15:2:22 | "source" | flow.js:131:43:131:43 | x | exclusiveTaintFlow | interflow.js:3:18:3:25 | "source" | interflow.js:18:10:18:14 | error | +typetrack +| additional-promises.js:3:5:3:18 | p.then(x => x) | additional-promises.js:3:12:3:12 | x | level | +| additional-promises.js:3:5:3:18 | p.then(x => x) | additional-promises.js:3:12:3:12 | x | store $PromiseResolveField$ | +| additional-promises.js:3:12:3:12 | x | additional-promises.js:2:13:2:57 | new Pin ... ct) {}) | load $PromiseResolveField$ | +| flow.js:5:7:5:14 | await p1 | flow.js:4:11:4:33 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:8:7:8:14 | await p2 | flow.js:7:11:7:59 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:11:7:11:14 | await p3 | flow.js:10:11:10:58 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:15:13:15:20 | await p4 | flow.js:13:11:13:58 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | level | +| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | store $PromiseResolveField$ | +| flow.js:20:31:20:31 | x | flow.js:20:2:20:24 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:36:22:41 | foo(x) | level | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:36:22:41 | foo(x) | store $PromiseResolveField$ | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:49:22:55 | sink(y) | level | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:49:22:55 | sink(y) | store $PromiseResolveField$ | +| flow.js:22:31:22:31 | x | flow.js:22:2:22:24 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:24:2:24:68 | new Pro ... ink(x)) | flow.js:24:61:24:67 | sink(x) | level | +| flow.js:24:2:24:68 | new Pro ... ink(x)) | flow.js:24:61:24:67 | sink(x) | store $PromiseResolveField$ | +| flow.js:24:56:24:56 | x | flow.js:24:2:24:49 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:61:26:66 | foo(x) | level | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:61:26:66 | foo(x) | store $PromiseResolveField$ | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:74:26:80 | sink(y) | level | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:74:26:80 | sink(y) | store $PromiseResolveField$ | +| flow.js:26:56:26:56 | x | flow.js:26:2:26:49 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:28:2:28:60 | Promise ... ink(z)) | flow.js:28:53:28:59 | sink(z) | level | +| flow.js:28:2:28:60 | Promise ... ink(z)) | flow.js:28:53:28:59 | sink(z) | store $PromiseResolveField$ | +| flow.js:28:30:28:30 | x | flow.js:28:2:28:23 | Promise ... ("foo") | load $PromiseResolveField$ | +| flow.js:28:48:28:48 | z | flow.js:28:2:28:41 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:30:2:30:60 | Promise ... ink(z)) | flow.js:30:53:30:59 | sink(z) | level | +| flow.js:30:2:30:60 | Promise ... ink(z)) | flow.js:30:53:30:59 | sink(z) | store $PromiseResolveField$ | +| flow.js:30:31:30:31 | x | flow.js:30:2:30:24 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:30:48:30:48 | z | flow.js:30:2:30:41 | Promise ... "foo") | load $PromiseResolveField$ | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:2:32:49 | new Pro ... ource)) | level | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:62:32:68 | sink(x) | level | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:62:32:68 | sink(x) | store $PromiseResolveField$ | +| flow.js:34:2:34:41 | Promise ... => { }) | flow.js:34:2:34:24 | Promise ... source) | level | +| flow.js:34:2:34:60 | Promise ... ink(a)) | flow.js:34:53:34:59 | sink(a) | level | +| flow.js:34:2:34:60 | Promise ... ink(a)) | flow.js:34:53:34:59 | sink(a) | store $PromiseResolveField$ | +| flow.js:34:48:34:48 | a | flow.js:34:2:34:41 | Promise ... => { }) | load $PromiseResolveField$ | +| flow.js:37:11:37:29 | p5.catch(() => { }) | flow.js:36:11:36:33 | Promise ... source) | level | +| flow.js:38:11:38:31 | p6.then ... ink(a)) | flow.js:38:24:38:30 | sink(a) | level | +| flow.js:38:11:38:31 | p6.then ... ink(a)) | flow.js:38:24:38:30 | sink(a) | store $PromiseResolveField$ | +| flow.js:38:19:38:19 | a | flow.js:37:11:37:29 | p5.catch(() => { }) | load $PromiseResolveField$ | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:2:40:65 | new Pro ... => { }) | level | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:78:40:84 | sink(x) | level | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:78:40:84 | sink(x) | store $PromiseResolveField$ | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:2:42:76 | new Pro ... => { }) | level | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:89:42:95 | sink(x) | level | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:89:42:95 | sink(x) | store $PromiseResolveField$ | +| flow.js:44:2:44:41 | Promise ... => { }) | flow.js:44:2:44:24 | Promise ... source) | level | +| flow.js:44:2:44:58 | Promise ... => { }) | flow.js:44:2:44:41 | Promise ... => { }) | level | +| flow.js:44:2:44:75 | Promise ... => { }) | flow.js:44:2:44:58 | Promise ... => { }) | level | +| flow.js:44:2:44:94 | Promise ... ink(a)) | flow.js:44:87:44:93 | sink(a) | level | +| flow.js:44:2:44:94 | Promise ... ink(a)) | flow.js:44:87:44:93 | sink(a) | store $PromiseResolveField$ | +| flow.js:44:82:44:82 | a | flow.js:44:2:44:75 | Promise ... => { }) | load $PromiseResolveField$ | +| flow.js:46:2:46:43 | Promise ... => { }) | flow.js:46:2:46:24 | Promise ... source) | level | +| flow.js:46:2:46:62 | Promise ... ink(a)) | flow.js:46:55:46:61 | sink(a) | level | +| flow.js:46:2:46:62 | Promise ... ink(a)) | flow.js:46:55:46:61 | sink(a) | store $PromiseResolveField$ | +| flow.js:46:50:46:50 | a | flow.js:46:2:46:43 | Promise ... => { }) | load $PromiseResolveField$ | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:2:48:36 | new Pro ... urce }) | level | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:49:48:55 | sink(x) | level | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:49:48:55 | sink(x) | store $PromiseResolveField$ | +| flow.js:51:10:51:29 | Promise.resolve(src) | flow.js:50:25:50:27 | src | level | +| flow.js:51:10:51:29 | Promise.resolve(src) | flow.js:50:25:50:27 | src | store $PromiseResolveField$ | +| flow.js:53:2:53:41 | createP ... ink(v)) | flow.js:53:34:53:40 | sink(v) | level | +| flow.js:53:2:53:41 | createP ... ink(v)) | flow.js:53:34:53:40 | sink(v) | store $PromiseResolveField$ | +| flow.js:53:29:53:29 | v | flow.js:53:2:53:22 | createP ... source) | load $PromiseResolveField$ | +| flow.js:57:12:57:31 | p9.finally(() => {}) | flow.js:56:11:56:27 | p8.then(() => {}) | level | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:57:12:57:31 | p9.finally(() => {}) | level | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:58:19:58:25 | sink(x) | level | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:58:19:58:25 | sink(x) | store $PromiseResolveField$ | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:61:12:61:29 | p11.then(() => {}) | level | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | level | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | store $PromiseResolveField$ | +| flow.js:65:3:65:56 | await n ... ource)) | flow.js:65:9:65:56 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:2:76:32 | chained ... => {}) | level | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | level | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | store $PromiseResolveField$ | +| flow.js:79:3:79:22 | p.then(x => sink(x)) | flow.js:79:15:79:21 | sink(x) | level | +| flow.js:79:3:79:22 | p.then(x => sink(x)) | flow.js:79:15:79:21 | sink(x) | store $PromiseResolveField$ | +| flow.js:79:10:79:10 | x | flow.js:78:32:78:32 | p | load $PromiseResolveField$ | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:83:32:83:32 | p | level | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:84:16:84:22 | sink(e) | level | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:84:16:84:22 | sink(e) | store $PromiseResolveField$ | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:3:89:27 | ("foo", ... => {}) | level | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:40:89:46 | sink(e) | level | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:40:89:46 | sink(e) | store $PromiseResolveField$ | +| flow.js:95:4:95:10 | await p | flow.js:93:33:93:33 | p | load $PromiseResolveField$ | +| flow.js:103:2:103:76 | new Pro ... ource}) | flow.js:103:2:103:48 | new Pro ... "BLA")) | level | +| flow.js:103:2:103:95 | new Pro ... ink(x)) | flow.js:103:88:103:94 | sink(x) | level | +| flow.js:103:2:103:95 | new Pro ... ink(x)) | flow.js:103:88:103:94 | sink(x) | store $PromiseResolveField$ | +| flow.js:103:83:103:83 | x | flow.js:103:2:103:76 | new Pro ... ource}) | load $PromiseResolveField$ | +| flow.js:105:2:105:77 | new Pro ... ource}) | flow.js:105:2:105:48 | new Pro ... "BLA")) | level | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:2:105:77 | new Pro ... ource}) | level | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:90:105:96 | sink(x) | level | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:90:105:96 | sink(x) | store $PromiseResolveField$ | +| flow.js:109:2:109:71 | new Pro ... jected) | flow.js:109:2:109:48 | new Pro ... "BLA")) | level | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:2:109:71 | new Pro ... jected) | level | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:84:109:90 | sink(x) | level | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:84:109:90 | sink(x) | store $PromiseResolveField$ | +| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | +| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | +| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:111:2:111:48 | new Pro ... "BLA")) | level | +| flow.js:111:2:111:88 | new Pro ... ink(x)) | flow.js:111:81:111:87 | sink(x) | level | +| flow.js:111:2:111:88 | new Pro ... ink(x)) | flow.js:111:81:111:87 | sink(x) | store $PromiseResolveField$ | +| flow.js:111:76:111:76 | x | flow.js:111:2:111:69 | new Pro ... jected) | load $PromiseResolveField$ | +| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | +| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | +| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:113:2:113:48 | new Pro ... "BLA")) | level | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:2:113:69 | new Pro ... jected) | level | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:82:113:88 | sink(x) | level | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:82:113:88 | sink(x) | store $PromiseResolveField$ | +| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | +| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | +| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:117:2:117:48 | new Pro ... "BLA")) | level | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:2:117:69 | new Pro ... solved) | level | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:82:117:88 | sink(x) | level | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:82:117:88 | sink(x) | store $PromiseResolveField$ | +| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | +| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | +| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:119:2:119:48 | new Pro ... "BLA")) | level | +| flow.js:119:2:119:88 | new Pro ... ink(x)) | flow.js:119:81:119:87 | sink(x) | level | +| flow.js:119:2:119:88 | new Pro ... ink(x)) | flow.js:119:81:119:87 | sink(x) | store $PromiseResolveField$ | +| flow.js:119:76:119:76 | x | flow.js:119:2:119:69 | new Pro ... solved) | load $PromiseResolveField$ | +| flow.js:121:2:121:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | +| flow.js:121:2:121:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:2:121:41 | Promise ... solved) | level | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:54:121:60 | sink(x) | level | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:54:121:60 | sink(x) | store $PromiseResolveField$ | +| flow.js:121:28:121:28 | x | flow.js:121:2:121:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:123:2:123:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | +| flow.js:123:2:123:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | +| flow.js:123:2:123:60 | Promise ... ink(x)) | flow.js:123:53:123:59 | sink(x) | level | +| flow.js:123:2:123:60 | Promise ... ink(x)) | flow.js:123:53:123:59 | sink(x) | store $PromiseResolveField$ | +| flow.js:123:28:123:28 | x | flow.js:123:2:123:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:123:48:123:48 | x | flow.js:123:2:123:41 | Promise ... solved) | load $PromiseResolveField$ | +| flow.js:125:2:125:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | +| flow.js:125:2:125:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:2:125:41 | Promise ... jected) | level | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:54:125:60 | sink(x) | level | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:54:125:60 | sink(x) | store $PromiseResolveField$ | +| flow.js:125:28:125:28 | x | flow.js:125:2:125:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:127:2:127:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | +| flow.js:127:2:127:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | +| flow.js:127:2:127:60 | Promise ... ink(x)) | flow.js:127:53:127:59 | sink(x) | level | +| flow.js:127:2:127:60 | Promise ... ink(x)) | flow.js:127:53:127:59 | sink(x) | store $PromiseResolveField$ | +| flow.js:127:28:127:28 | x | flow.js:127:2:127:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:127:48:127:48 | x | flow.js:127:2:127:41 | Promise ... jected) | load $PromiseResolveField$ | +| flow.js:129:2:129:52 | new Pro ... olved)) | flow.js:115:17:115:39 | Promise ... source) | level | +| flow.js:129:2:129:52 | new Pro ... olved)) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | +| flow.js:129:2:129:71 | new Pro ... ink(x)) | flow.js:129:64:129:70 | sink(x) | level | +| flow.js:129:2:129:71 | new Pro ... ink(x)) | flow.js:129:64:129:70 | sink(x) | store $PromiseResolveField$ | +| flow.js:129:59:129:59 | x | flow.js:129:2:129:52 | new Pro ... olved)) | load $PromiseResolveField$ | +| flow.js:131:2:131:26 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | +| flow.js:131:2:131:26 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | +| flow.js:131:2:131:45 | Promise ... ink(x)) | flow.js:131:38:131:44 | sink(x) | level | +| flow.js:131:2:131:45 | Promise ... ink(x)) | flow.js:131:38:131:44 | sink(x) | store $PromiseResolveField$ | +| flow.js:131:33:131:33 | x | flow.js:131:2:131:26 | Promise ... solved) | load $PromiseResolveField$ | +| interflow.js:6:3:9:23 | loadScr ... eError) | interflow.js:6:3:8:26 | loadScr ... () { }) | level | +| promises.js:6:26:6:28 | val | promises.js:3:17:5:4 | new Pro ... );\\n }) | load $PromiseResolveField$ | +| promises.js:18:18:18:18 | v | promises.js:10:18:17:4 | new Pro ... );\\n }) | load $PromiseResolveField$ | +| promises.js:23:3:25:4 | promise ... v;\\n }) | promises.js:10:18:17:4 | new Pro ... );\\n }) | level | +| promises.js:26:3:28:4 | promise ... v;\\n }) | promises.js:10:18:17:4 | new Pro ... );\\n }) | level | +| promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:34:17:34:22 | source | level | +| promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:34:17:34:22 | source | store $PromiseResolveField$ | +| promises.js:36:28:36:30 | val | promises.js:33:19:35:6 | new Pro ... \\n }) | load $PromiseResolveField$ | +| promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:44:17:44:22 | source | level | +| promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:44:17:44:22 | source | store $PromiseResolveField$ | +| promises.js:46:28:46:30 | val | promises.js:43:19:45:6 | Q.Promi ... \\n }) | load $PromiseResolveField$ | +| promises.js:54:28:54:30 | val | promises.js:53:19:53:41 | Promise ... source) | load $PromiseResolveField$ | +| promises.js:63:28:63:30 | val | promises.js:62:19:62:41 | Promise ... source) | load $PromiseResolveField$ | +| promises.js:71:34:71:36 | val | promises.js:71:5:71:27 | Promise ... source) | load $PromiseResolveField$ | +| promises.js:72:48:72:50 | val | promises.js:72:5:72:41 | new Pro ... ource)) | load $PromiseResolveField$ | +| promises.js:75:27:75:29 | val | promises.js:75:5:75:20 | resolver.promise | load $PromiseResolveField$ | +| promises.js:79:19:79:41 | Promise ... source) | promises.js:78:11:78:16 | source | level | +| promises.js:79:19:79:41 | Promise ... source) | promises.js:78:11:78:16 | source | store $PromiseResolveField$ | +| promises.js:80:28:80:30 | val | promises.js:79:19:79:41 | Promise ... source) | load $PromiseResolveField$ | diff --git a/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected b/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected index be5f2b10245..592ec644363 100644 --- a/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected +++ b/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected @@ -27,3 +27,4 @@ | tst-file-names.js:45:12:45:42 | globule ... /*.js") | | tst-file-names.js:46:12:46:51 | globule ... .js"]}) | | tst-file-names.js:47:12:47:52 | globule ... b.js"]) | +| tst-file-names.js:51:15:51:23 | await foo | From 4f068685e14ad17e425556c86c7f1d56d93dd634 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 26 Mar 2020 10:46:24 +0100 Subject: [PATCH 143/459] C++: Add AssignExpr + Initializer to lib overview --- docs/language/learn-ql/cpp/introduce-libraries-cpp.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 6bea8d40c2c..9e7e910e78e 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -31,7 +31,7 @@ This table lists `Declaration `__ | | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | `LocalVariable `__ | | +| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | `LocalVariable `__ | See also `Initializer `__ | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``class`` *C* ``{`` ... ``int`` *var* ``;`` ... ``}`` | `MemberVariable `__ | | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -286,6 +286,8 @@ This table lists subclasses of `Expr `__ ``)`` | `NoExceptExpr `__ | | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| `Expr `__ ``=`` `Expr `__ | `AssignExpr `__ | See also `Initializer `__ | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | `Expr `__ ``+=`` `Expr `__ | | `AssignAddExpr `__ | | | | | `AssignPointerAddExpr `__ | | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ From fbef146a497e492d3cc5deb877c6b0f147421c34 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 26 Mar 2020 11:39:20 +0100 Subject: [PATCH 144/459] C++: Remove PositionalArgumentWithoutWriteSideEffectNode (since not all arguments need a PostUpdateNode). Also generalized the added flow rule in simpleLocalFlowStep since there isn't always a ChiInstruction - for instance of it's a write to a struct that only has a single field. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 36 ++++++++----------- .../dataflow/fields/ir-flow.expected | 35 ++++++++++++++++++ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 93aa394d599..a811cd795ac 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -218,7 +218,17 @@ abstract class PostUpdateNode extends InstructionNode { override string toString() { result = getPreUpdateNode().toString() + " [post update]" } } -abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { } +abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { + final Instruction getInstructionOrChi() { + exists(ChiInstruction chi | + // TODO: This should be a non-conflated ChiInstruction once #3123 is merged + chi.getPartial() = getInstruction() and + result = chi + ) + or + result = getInstruction() + } +} class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { override StoreInstruction instr; @@ -268,22 +278,6 @@ class DefinitionByReferenceNode extends PartialDefinitionNode { override string toString() { result = "ref arg " + getPreUpdateNode().toString() } } -class PositionalArgumentWithoutWriteSideEffectNode extends PartialDefinitionNode { - override CallInstruction instr; - PositionalArgumentOperand op; - - PositionalArgumentWithoutWriteSideEffectNode() { - instr.getAnOperand() = op and - not exists(WriteSideEffectInstruction write | - write.getIndex() = op.getIndex() and write.getPrimaryInstruction() = instr - ) - } - - override Node getPreUpdateNode() { result.asInstruction() = op.getDef() } - - override string toString() { result = "no change to " + op.toString() } -} - /** * A `Node` corresponding to a variable in the program, as opposed to the * value of that variable at some particular point. This can be used for @@ -365,10 +359,10 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) or - exists(ChiInstruction chi, LoadInstruction load | - chi.getPartial() = nodeFrom.(PartialDefinitionNode).getInstruction() and - // TODO: This can probably be getSourceValue() after #3112 is merged - load.getSourceValueOperand().getAnyDef() = chi and + exists(LoadInstruction load | + // TODO: These can probably be getSourceValue() after #3112 is merged + load.getSourceValueOperand().getAnyDef() = + nodeFrom.(PartialDefinitionNode).getInstructionOrChi() and nodeTo.asInstruction() = load.getSourceAddress().(FieldAddressInstruction).getObjectAddress() ) } diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index c66255c7338..3e665a81199 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -15,27 +15,48 @@ edges | aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | aliasing.cpp:30:8:30:9 | s2 [m1] : void | | aliasing.cpp:29:8:29:9 | s1 [m1] : void | aliasing.cpp:29:11:29:12 | m1 | | aliasing.cpp:30:8:30:9 | s2 [m1] : void | aliasing.cpp:30:11:30:12 | m1 | +| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] [m1] : void | | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] [m1] : void | aliasing.cpp:38:8:38:9 | s1 [m1] : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:38:8:38:9 | s1 [m1] : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void | | aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void | aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | s2 [post update] : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:79:3:79:22 | s [post update] [m1] : void | | aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:79:3:79:22 | s [post update] [m1] : void | aliasing.cpp:80:10:80:10 | s [m1] : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | s [post update] : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:80:10:80:10 | s [m1] : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void | | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void | aliasing.cpp:87:10:87:10 | s [m1] : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:87:10:87:10 | s [m1] : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:92:3:92:23 | s [post update] [m1] : void | | aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:93:12:93:13 | m1 | +| aliasing.cpp:92:3:92:23 | s [post update] [m1] : void | aliasing.cpp:93:10:93:10 | s [m1] : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | s [post update] : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | +| aliasing.cpp:93:10:93:10 | s [m1] : void | aliasing.cpp:93:12:93:13 | m1 | +| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:20:20:20:29 | VariableAddress [post update] [a] : void | | struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:20:20:20:29 | VariableAddress [post update] [a] : void | struct_init.c:22:8:22:9 | ab [a] : void | | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | VariableAddress [post update] : void | | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:22:8:22:9 | ab [a] : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:27:7:27:16 | FieldAddress [post update] [a] : void | | struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:31:23:31:23 | a | +| struct_init.c:27:7:27:16 | FieldAddress [post update] [a] : void | struct_init.c:31:14:31:21 | nestedAB [a] : void | | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | FieldAddress [post update] : void | | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | +| struct_init.c:31:14:31:21 | nestedAB [a] : void | struct_init.c:31:23:31:23 | a | nodes | A.cpp:126:5:126:5 | ref arg b [c] : void | semmle.label | ref arg b [c] : void | | A.cpp:126:12:126:18 | new : void | semmle.label | new : void | @@ -57,25 +78,39 @@ nodes | aliasing.cpp:30:8:30:9 | s2 [m1] : void | semmle.label | s2 [m1] : void | | aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | +| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:38:8:38:9 | s1 [m1] : void | semmle.label | s1 [m1] : void | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | | aliasing.cpp:42:3:42:22 | s2 [post update] : void | semmle.label | s2 [post update] : void | +| aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void | semmle.label | s2 [post update] [m1] : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | semmle.label | (reference dereference) [m1] : void | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | | aliasing.cpp:79:3:79:22 | s [post update] : void | semmle.label | s [post update] : void | +| aliasing.cpp:79:3:79:22 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:80:10:80:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | +| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:87:10:87:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | | aliasing.cpp:92:3:92:23 | s [post update] : void | semmle.label | s [post update] : void | +| aliasing.cpp:92:3:92:23 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:93:10:93:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | | struct_init.c:20:20:20:29 | VariableAddress [post update] : void | semmle.label | VariableAddress [post update] : void | +| struct_init.c:20:20:20:29 | VariableAddress [post update] [a] : void | semmle.label | VariableAddress [post update] [a] : void | | struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void | +| struct_init.c:22:8:22:9 | ab [a] : void | semmle.label | ab [a] : void | | struct_init.c:22:11:22:11 | a | semmle.label | a | | struct_init.c:27:7:27:16 | FieldAddress [post update] : void | semmle.label | FieldAddress [post update] : void | +| struct_init.c:27:7:27:16 | FieldAddress [post update] [a] : void | semmle.label | FieldAddress [post update] [a] : void | | struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void | +| struct_init.c:31:14:31:21 | nestedAB [a] : void | semmle.label | nestedAB [a] : void | | struct_init.c:31:23:31:23 | a | semmle.label | a | #select | A.cpp:132:10:132:13 | (void *)... | A.cpp:126:12:126:18 | new : void | A.cpp:132:10:132:13 | (void *)... | (void *)... flows from $@ | A.cpp:126:12:126:18 | new : void | new : void | From c6c613840a09768a9267cd582e0768fd65068e56 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 26 Mar 2020 11:43:40 +0100 Subject: [PATCH 145/459] C++: Removed toString from PostUpdateNodes. They were more confusing than helpful --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 4 - .../dataflow/fields/ir-flow.expected | 122 +++++++++--------- 2 files changed, 61 insertions(+), 65 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index a811cd795ac..123841c47cf 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -214,8 +214,6 @@ abstract class PostUpdateNode extends InstructionNode { * Gets the node before the state update. */ abstract Node getPreUpdateNode(); - - override string toString() { result = getPreUpdateNode().toString() + " [post update]" } } abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { @@ -274,8 +272,6 @@ class DefinitionByReferenceNode extends PartialDefinitionNode { Parameter getParameter() { exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex())) } - - override string toString() { result = "ref arg " + getPreUpdateNode().toString() } } /** diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index 3e665a81199..f455b37bf49 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -1,114 +1,114 @@ edges -| A.cpp:126:5:126:5 | ref arg b [c] : void | A.cpp:131:8:131:8 | ref arg b [c] : void | -| A.cpp:126:12:126:18 | new : void | A.cpp:126:5:126:5 | ref arg b [c] : void | -| A.cpp:131:8:131:8 | ref arg b [c] : void | A.cpp:132:10:132:10 | b [c] : void | +| A.cpp:126:5:126:5 | IndirectMayWriteSideEffect [c] : void | A.cpp:131:8:131:8 | BufferMayWriteSideEffect [c] : void | +| A.cpp:126:12:126:18 | new : void | A.cpp:126:5:126:5 | IndirectMayWriteSideEffect [c] : void | +| A.cpp:131:8:131:8 | BufferMayWriteSideEffect [c] : void | A.cpp:132:10:132:10 | b [c] : void | | A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c | | A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c : void | | A.cpp:132:13:132:13 | c : void | A.cpp:132:10:132:13 | (void *)... | -| aliasing.cpp:9:3:9:22 | s [post update] : void | aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | -| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | -| aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:9:3:9:22 | s [post update] : void | -| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | -| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | -| aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | -| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | aliasing.cpp:29:8:29:9 | s1 [m1] : void | -| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | aliasing.cpp:30:8:30:9 | s2 [m1] : void | +| aliasing.cpp:9:3:9:22 | Store : void | aliasing.cpp:9:3:9:22 | Store [m1] : void | +| aliasing.cpp:9:3:9:22 | Store [m1] : void | aliasing.cpp:25:17:25:19 | BufferMayWriteSideEffect [m1] : void | +| aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:9:3:9:22 | Store : void | +| aliasing.cpp:13:3:13:21 | Store : void | aliasing.cpp:13:3:13:21 | Store [m1] : void | +| aliasing.cpp:13:3:13:21 | Store [m1] : void | aliasing.cpp:26:19:26:20 | BufferMayWriteSideEffect [m1] : void | +| aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:13:3:13:21 | Store : void | +| aliasing.cpp:25:17:25:19 | BufferMayWriteSideEffect [m1] : void | aliasing.cpp:29:8:29:9 | s1 [m1] : void | +| aliasing.cpp:26:19:26:20 | BufferMayWriteSideEffect [m1] : void | aliasing.cpp:30:8:30:9 | s2 [m1] : void | | aliasing.cpp:29:8:29:9 | s1 [m1] : void | aliasing.cpp:29:11:29:12 | m1 | | aliasing.cpp:30:8:30:9 | s2 [m1] : void | aliasing.cpp:30:11:30:12 | m1 | -| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] [m1] : void | -| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:38:11:38:12 | m1 | -| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] [m1] : void | aliasing.cpp:38:8:38:9 | s1 [m1] : void | -| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | +| aliasing.cpp:37:3:37:24 | Store : void | aliasing.cpp:37:3:37:24 | Store [m1] : void | +| aliasing.cpp:37:3:37:24 | Store : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:37:3:37:24 | Store [m1] : void | aliasing.cpp:38:8:38:9 | s1 [m1] : void | +| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | Store : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | | aliasing.cpp:38:8:38:9 | s1 [m1] : void | aliasing.cpp:38:11:38:12 | m1 | -| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void | -| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void | aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | -| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | s2 [post update] : void | +| aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:42:3:42:22 | Store [m1] : void | +| aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:42:3:42:22 | Store [m1] : void | aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | +| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | Store : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | | aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:79:3:79:22 | s [post update] [m1] : void | -| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:80:12:80:13 | m1 | -| aliasing.cpp:79:3:79:22 | s [post update] [m1] : void | aliasing.cpp:80:10:80:10 | s [m1] : void | -| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | s [post update] : void | +| aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:79:3:79:22 | Store [m1] : void | +| aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:79:3:79:22 | Store [m1] : void | aliasing.cpp:80:10:80:10 | s [m1] : void | +| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | Store : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | | aliasing.cpp:80:10:80:10 | s [m1] : void | aliasing.cpp:80:12:80:13 | m1 | -| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void | -| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:87:12:87:13 | m1 | -| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void | aliasing.cpp:87:10:87:10 | s [m1] : void | -| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | +| aliasing.cpp:86:3:86:21 | Store : void | aliasing.cpp:86:3:86:21 | Store [m1] : void | +| aliasing.cpp:86:3:86:21 | Store : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:86:3:86:21 | Store [m1] : void | aliasing.cpp:87:10:87:10 | s [m1] : void | +| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | Store : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | | aliasing.cpp:87:10:87:10 | s [m1] : void | aliasing.cpp:87:12:87:13 | m1 | -| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:92:3:92:23 | s [post update] [m1] : void | -| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:92:3:92:23 | s [post update] [m1] : void | aliasing.cpp:93:10:93:10 | s [m1] : void | -| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | s [post update] : void | +| aliasing.cpp:92:3:92:23 | Store : void | aliasing.cpp:92:3:92:23 | Store [m1] : void | +| aliasing.cpp:92:3:92:23 | Store : void | aliasing.cpp:93:12:93:13 | m1 | +| aliasing.cpp:92:3:92:23 | Store [m1] : void | aliasing.cpp:93:10:93:10 | s [m1] : void | +| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | Store : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | | aliasing.cpp:93:10:93:10 | s [m1] : void | aliasing.cpp:93:12:93:13 | m1 | -| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:20:20:20:29 | VariableAddress [post update] [a] : void | -| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:22:11:22:11 | a | -| struct_init.c:20:20:20:29 | VariableAddress [post update] [a] : void | struct_init.c:22:8:22:9 | ab [a] : void | -| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | VariableAddress [post update] : void | +| struct_init.c:20:20:20:29 | Store : void | struct_init.c:20:20:20:29 | Store [a] : void | +| struct_init.c:20:20:20:29 | Store : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:20:20:20:29 | Store [a] : void | struct_init.c:22:8:22:9 | ab [a] : void | +| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | Store : void | | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | | struct_init.c:22:8:22:9 | ab [a] : void | struct_init.c:22:11:22:11 | a | -| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:27:7:27:16 | FieldAddress [post update] [a] : void | -| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:31:23:31:23 | a | -| struct_init.c:27:7:27:16 | FieldAddress [post update] [a] : void | struct_init.c:31:14:31:21 | nestedAB [a] : void | -| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | FieldAddress [post update] : void | +| struct_init.c:27:7:27:16 | Store : void | struct_init.c:27:7:27:16 | Store [a] : void | +| struct_init.c:27:7:27:16 | Store : void | struct_init.c:31:23:31:23 | a | +| struct_init.c:27:7:27:16 | Store [a] : void | struct_init.c:31:14:31:21 | nestedAB [a] : void | +| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | Store : void | | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | | struct_init.c:31:14:31:21 | nestedAB [a] : void | struct_init.c:31:23:31:23 | a | nodes -| A.cpp:126:5:126:5 | ref arg b [c] : void | semmle.label | ref arg b [c] : void | +| A.cpp:126:5:126:5 | IndirectMayWriteSideEffect [c] : void | semmle.label | IndirectMayWriteSideEffect [c] : void | | A.cpp:126:12:126:18 | new : void | semmle.label | new : void | -| A.cpp:131:8:131:8 | ref arg b [c] : void | semmle.label | ref arg b [c] : void | +| A.cpp:131:8:131:8 | BufferMayWriteSideEffect [c] : void | semmle.label | BufferMayWriteSideEffect [c] : void | | A.cpp:132:10:132:10 | b [c] : void | semmle.label | b [c] : void | | A.cpp:132:10:132:13 | (void *)... | semmle.label | (void *)... | | A.cpp:132:13:132:13 | c | semmle.label | c | | A.cpp:132:13:132:13 | c : void | semmle.label | c : void | -| aliasing.cpp:9:3:9:22 | s [post update] : void | semmle.label | s [post update] : void | -| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void | +| aliasing.cpp:9:3:9:22 | Store : void | semmle.label | Store : void | +| aliasing.cpp:9:3:9:22 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:9:11:9:20 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | -| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void | +| aliasing.cpp:13:3:13:21 | Store : void | semmle.label | Store : void | +| aliasing.cpp:13:3:13:21 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:13:10:13:19 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | semmle.label | ref arg & ... [m1] : void | -| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | semmle.label | ref arg (reference to) [m1] : void | +| aliasing.cpp:25:17:25:19 | BufferMayWriteSideEffect [m1] : void | semmle.label | BufferMayWriteSideEffect [m1] : void | +| aliasing.cpp:26:19:26:20 | BufferMayWriteSideEffect [m1] : void | semmle.label | BufferMayWriteSideEffect [m1] : void | | aliasing.cpp:29:8:29:9 | s1 [m1] : void | semmle.label | s1 [m1] : void | | aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 | | aliasing.cpp:30:8:30:9 | s2 [m1] : void | semmle.label | s2 [m1] : void | | aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | -| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | -| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void | +| aliasing.cpp:37:3:37:24 | Store : void | semmle.label | Store : void | +| aliasing.cpp:37:3:37:24 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:38:8:38:9 | s1 [m1] : void | semmle.label | s1 [m1] : void | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | -| aliasing.cpp:42:3:42:22 | s2 [post update] : void | semmle.label | s2 [post update] : void | -| aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void | semmle.label | s2 [post update] [m1] : void | +| aliasing.cpp:42:3:42:22 | Store : void | semmle.label | Store : void | +| aliasing.cpp:42:3:42:22 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | semmle.label | (reference dereference) [m1] : void | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | -| aliasing.cpp:79:3:79:22 | s [post update] : void | semmle.label | s [post update] : void | -| aliasing.cpp:79:3:79:22 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void | +| aliasing.cpp:79:3:79:22 | Store : void | semmle.label | Store : void | +| aliasing.cpp:79:3:79:22 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:80:10:80:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | -| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void | -| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void | +| aliasing.cpp:86:3:86:21 | Store : void | semmle.label | Store : void | +| aliasing.cpp:86:3:86:21 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:87:10:87:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | -| aliasing.cpp:92:3:92:23 | s [post update] : void | semmle.label | s [post update] : void | -| aliasing.cpp:92:3:92:23 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void | +| aliasing.cpp:92:3:92:23 | Store : void | semmle.label | Store : void | +| aliasing.cpp:92:3:92:23 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:93:10:93:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | -| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | semmle.label | VariableAddress [post update] : void | -| struct_init.c:20:20:20:29 | VariableAddress [post update] [a] : void | semmle.label | VariableAddress [post update] [a] : void | +| struct_init.c:20:20:20:29 | Store : void | semmle.label | Store : void | +| struct_init.c:20:20:20:29 | Store [a] : void | semmle.label | Store [a] : void | | struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void | | struct_init.c:22:8:22:9 | ab [a] : void | semmle.label | ab [a] : void | | struct_init.c:22:11:22:11 | a | semmle.label | a | -| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | semmle.label | FieldAddress [post update] : void | -| struct_init.c:27:7:27:16 | FieldAddress [post update] [a] : void | semmle.label | FieldAddress [post update] [a] : void | +| struct_init.c:27:7:27:16 | Store : void | semmle.label | Store : void | +| struct_init.c:27:7:27:16 | Store [a] : void | semmle.label | Store [a] : void | | struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void | | struct_init.c:31:14:31:21 | nestedAB [a] : void | semmle.label | nestedAB [a] : void | | struct_init.c:31:23:31:23 | a | semmle.label | a | From db8d61c3be0c9bd3f75e5fd771a4b02843980540 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 26 Mar 2020 12:26:17 +0100 Subject: [PATCH 146/459] C#: Remove compiler warning in `Remote.qll` --- .../semmle/code/csharp/security/dataflow/flowsinks/Remote.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll index 19451b14194..10885d52a16 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll @@ -3,7 +3,7 @@ */ import csharp -private import Email +private import Email::Email private import ExternalLocationSink private import Html private import semmle.code.csharp.security.dataflow.XSS From 816968d102e62eccb2c65b28448dcfe2042371bc Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 26 Mar 2020 11:59:57 +0000 Subject: [PATCH 147/459] JS: Rename test files to avoid clash --- .../Constants/Constants.expected | 4 +- .../Constants/{tst.ts => tst2.ts} | 0 .../DataFlow/enclosingExpr.expected | 60 +++++++++---------- .../library-tests/DataFlow/flowStep.expected | 28 ++++----- .../DataFlow/getIntValue.expected | 4 +- .../DataFlow/incomplete.expected | 24 ++++---- .../DataFlow/parameters.expected | 2 +- .../library-tests/DataFlow/sources.expected | 24 ++++---- .../DataFlow/{tst.ts => tst2.ts} | 0 .../Decorators/Decoratable.expected | 22 +++---- .../Decorators/Decorator.expected | 22 +++---- .../Decorators/{tst.ts => tst2.ts} | 0 .../FileTypes/FileTypes.expected | 10 ++-- .../FileTypes/{test.js => jsTest.js} | 0 .../FileTypes/{test.jsx => jsxTest.jsx} | 0 .../FileTypes/{test.mjs => mjsTest.mjs} | 0 .../FileTypes/{test.ts => tsTest.ts} | 0 .../FileTypes/{test.tsx => tsxTest.tsx} | 0 .../Flow/AbstractValues.expected | 8 +-- .../test/library-tests/Flow/abseval.expected | 8 +-- .../library-tests/Flow/getAPrototype.expected | 2 +- .../library-tests/Flow/{tst.ts => tsTest.ts} | 0 .../ql/test/library-tests/Flow/types.expected | 6 +- .../LocalObjects/{tst.ts => tst2.ts} | 0 .../test/library-tests/NPM/Modules.expected | 2 +- .../NPM/NPMPackage_getMainModule.expected | 2 +- .../node_modules/b/lib/{index.ts => util.ts} | 0 .../Electron/BrowserObject.expected | 12 ++-- .../frameworks/Electron/WebContents.expected | 4 +- .../{electron.d.ts => electronTs.d.ts} | 0 .../Electron/{electron.ts => electronTs.ts} | 2 +- .../FileWithExtractionMetrics.expected | 2 +- .../FileWithExtractionMetrics_length.expected | 2 +- .../FileWithExtractionMetrics_phases.expected | 18 +++--- .../meta/Extraction/{tst.ts => tst3.ts} | 0 .../ConflictingFunctions/{tst.ts => tst2.ts} | 0 .../UnusedProperty/UnusedProperty.expected | 2 +- .../UnusedProperty/{tst.ts => tst2.ts} | 0 .../SuspiciousPropAccess.expected | 2 +- .../SuspiciousPropAccess/{tst.ts => tst2.ts} | 0 .../UseOfReturnlessFunction.expected | 2 +- .../{tst.ts => tst2.ts} | 0 42 files changed, 137 insertions(+), 137 deletions(-) rename javascript/ql/test/library-tests/Constants/{tst.ts => tst2.ts} (100%) rename javascript/ql/test/library-tests/DataFlow/{tst.ts => tst2.ts} (100%) rename javascript/ql/test/library-tests/Decorators/{tst.ts => tst2.ts} (100%) rename javascript/ql/test/library-tests/FileTypes/{test.js => jsTest.js} (100%) rename javascript/ql/test/library-tests/FileTypes/{test.jsx => jsxTest.jsx} (100%) rename javascript/ql/test/library-tests/FileTypes/{test.mjs => mjsTest.mjs} (100%) rename javascript/ql/test/library-tests/FileTypes/{test.ts => tsTest.ts} (100%) rename javascript/ql/test/library-tests/FileTypes/{test.tsx => tsxTest.tsx} (100%) rename javascript/ql/test/library-tests/Flow/{tst.ts => tsTest.ts} (100%) rename javascript/ql/test/library-tests/LocalObjects/{tst.ts => tst2.ts} (100%) rename javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/{index.ts => util.ts} (100%) rename javascript/ql/test/library-tests/frameworks/Electron/{electron.d.ts => electronTs.d.ts} (100%) rename javascript/ql/test/library-tests/frameworks/Electron/{electron.ts => electronTs.ts} (72%) rename javascript/ql/test/library-tests/meta/Extraction/{tst.ts => tst3.ts} (100%) rename javascript/ql/test/query-tests/Declarations/ConflictingFunctions/{tst.ts => tst2.ts} (100%) rename javascript/ql/test/query-tests/Declarations/UnusedProperty/{tst.ts => tst2.ts} (100%) rename javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/{tst.ts => tst2.ts} (100%) rename javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/{tst.ts => tst2.ts} (100%) diff --git a/javascript/ql/test/library-tests/Constants/Constants.expected b/javascript/ql/test/library-tests/Constants/Constants.expected index 8bb5f427ec5..75a63830277 100644 --- a/javascript/ql/test/library-tests/Constants/Constants.expected +++ b/javascript/ql/test/library-tests/Constants/Constants.expected @@ -1,3 +1,5 @@ +| tst2.ts:1:13:1:21 | 1 | +| tst2.ts:1:21:1:21 | 1 | | tst.js:1:1:1:3 | "a" | | tst.js:2:1:2:3 | "b" | | tst.js:2:1:2:9 | "b" + "c" | @@ -59,5 +61,3 @@ | tst.js:48:1:48:7 | x.p = 1 | | tst.js:48:7:48:7 | 1 | | tst.js:49:6:49:6 | 1 | -| tst.ts:1:13:1:21 | 1 | -| tst.ts:1:21:1:21 | 1 | diff --git a/javascript/ql/test/library-tests/Constants/tst.ts b/javascript/ql/test/library-tests/Constants/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/Constants/tst.ts rename to javascript/ql/test/library-tests/Constants/tst2.ts diff --git a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected index b7da1347fce..c5e91b074fe 100644 --- a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected +++ b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected @@ -35,6 +35,36 @@ | sources.js:11:14:11:16 | key | sources.js:11:14:11:16 | key | | sources.js:11:23:11:27 | array | sources.js:11:23:11:27 | array | | sources.js:11:32:11:34 | key | sources.js:11:32:11:34 | key | +| tst2.ts:1:18:1:18 | A | tst2.ts:1:18:1:18 | A | +| tst2.ts:2:14:2:14 | x | tst2.ts:2:14:2:14 | x | +| tst2.ts:2:14:2:19 | x = 42 | tst2.ts:2:14:2:19 | x = 42 | +| tst2.ts:2:18:2:19 | 42 | tst2.ts:2:18:2:19 | 42 | +| tst2.ts:3:3:3:6 | setX | tst2.ts:3:3:3:6 | setX | +| tst2.ts:3:3:3:8 | setX() | tst2.ts:3:3:3:8 | setX() | +| tst2.ts:4:3:4:3 | x | tst2.ts:4:3:4:3 | x | +| tst2.ts:7:10:7:13 | setX | tst2.ts:7:10:7:13 | setX | +| tst2.ts:8:3:8:3 | A | tst2.ts:8:3:8:3 | A | +| tst2.ts:8:3:8:5 | A.x | tst2.ts:8:3:8:5 | A.x | +| tst2.ts:8:3:8:10 | A.x = 23 | tst2.ts:8:3:8:10 | A.x = 23 | +| tst2.ts:8:5:8:5 | x | tst2.ts:8:5:8:5 | x | +| tst2.ts:8:9:8:10 | 23 | tst2.ts:8:9:8:10 | 23 | +| tst2.ts:11:5:11:7 | nd2 | tst2.ts:11:5:11:7 | nd2 | +| tst2.ts:11:5:11:23 | nd2 = A.x as number | tst2.ts:11:5:11:23 | nd2 = A.x as number | +| tst2.ts:11:11:11:11 | A | tst2.ts:11:11:11:11 | A | +| tst2.ts:11:11:11:13 | A.x | tst2.ts:11:11:11:13 | A.x | +| tst2.ts:11:11:11:23 | A.x as number | tst2.ts:11:11:11:23 | A.x as number | +| tst2.ts:11:13:11:13 | x | tst2.ts:11:13:11:13 | x | +| tst2.ts:13:7:13:16 | StringList | tst2.ts:13:7:13:16 | StringList | +| tst2.ts:13:26:13:29 | List | tst2.ts:13:26:13:29 | List | +| tst2.ts:13:26:13:37 | List | tst2.ts:13:26:13:37 | List | +| tst2.ts:13:39:13:38 | (...arg ... rgs); } | tst2.ts:13:39:13:38 | (...arg ... rgs); } | +| tst2.ts:13:39:13:38 | ...args | tst2.ts:13:39:13:38 | ...args | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | constructor | tst2.ts:13:39:13:38 | constructor | +| tst2.ts:13:39:13:38 | super | tst2.ts:13:39:13:38 | super | +| tst2.ts:13:39:13:38 | super(...args) | tst2.ts:13:39:13:38 | super(...args) | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | @@ -289,33 +319,3 @@ | tst.js:115:1:115:12 | Array.call() | tst.js:115:1:115:12 | Array.call() | | tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | | tst.js:115:7:115:10 | call | tst.js:115:7:115:10 | call | -| tst.ts:1:18:1:18 | A | tst.ts:1:18:1:18 | A | -| tst.ts:2:14:2:14 | x | tst.ts:2:14:2:14 | x | -| tst.ts:2:14:2:19 | x = 42 | tst.ts:2:14:2:19 | x = 42 | -| tst.ts:2:18:2:19 | 42 | tst.ts:2:18:2:19 | 42 | -| tst.ts:3:3:3:6 | setX | tst.ts:3:3:3:6 | setX | -| tst.ts:3:3:3:8 | setX() | tst.ts:3:3:3:8 | setX() | -| tst.ts:4:3:4:3 | x | tst.ts:4:3:4:3 | x | -| tst.ts:7:10:7:13 | setX | tst.ts:7:10:7:13 | setX | -| tst.ts:8:3:8:3 | A | tst.ts:8:3:8:3 | A | -| tst.ts:8:3:8:5 | A.x | tst.ts:8:3:8:5 | A.x | -| tst.ts:8:3:8:10 | A.x = 23 | tst.ts:8:3:8:10 | A.x = 23 | -| tst.ts:8:5:8:5 | x | tst.ts:8:5:8:5 | x | -| tst.ts:8:9:8:10 | 23 | tst.ts:8:9:8:10 | 23 | -| tst.ts:11:5:11:7 | nd2 | tst.ts:11:5:11:7 | nd2 | -| tst.ts:11:5:11:23 | nd2 = A.x as number | tst.ts:11:5:11:23 | nd2 = A.x as number | -| tst.ts:11:11:11:11 | A | tst.ts:11:11:11:11 | A | -| tst.ts:11:11:11:13 | A.x | tst.ts:11:11:11:13 | A.x | -| tst.ts:11:11:11:23 | A.x as number | tst.ts:11:11:11:23 | A.x as number | -| tst.ts:11:13:11:13 | x | tst.ts:11:13:11:13 | x | -| tst.ts:13:7:13:16 | StringList | tst.ts:13:7:13:16 | StringList | -| tst.ts:13:26:13:29 | List | tst.ts:13:26:13:29 | List | -| tst.ts:13:26:13:37 | List | tst.ts:13:26:13:37 | List | -| tst.ts:13:39:13:38 | (...arg ... rgs); } | tst.ts:13:39:13:38 | (...arg ... rgs); } | -| tst.ts:13:39:13:38 | ...args | tst.ts:13:39:13:38 | ...args | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | constructor | tst.ts:13:39:13:38 | constructor | -| tst.ts:13:39:13:38 | super | tst.ts:13:39:13:38 | super | -| tst.ts:13:39:13:38 | super(...args) | tst.ts:13:39:13:38 | super(...args) | diff --git a/javascript/ql/test/library-tests/DataFlow/flowStep.expected b/javascript/ql/test/library-tests/DataFlow/flowStep.expected index 31e11c60b74..4bb0eabd7f6 100644 --- a/javascript/ql/test/library-tests/DataFlow/flowStep.expected +++ b/javascript/ql/test/library-tests/DataFlow/flowStep.expected @@ -12,6 +12,20 @@ | sources.js:10:12:10:14 | key | sources.js:10:28:10:30 | key | | sources.js:11:12:11:18 | key | sources.js:11:32:11:34 | key | | sources.js:11:14:11:16 | key | sources.js:11:12:11:18 | key | +| tst2.ts:1:1:1:1 | A | tst2.ts:1:18:1:18 | A | +| tst2.ts:1:1:1:1 | A | tst2.ts:7:1:7:0 | A | +| tst2.ts:1:8:5:1 | A | tst2.ts:7:1:7:0 | A | +| tst2.ts:1:8:5:1 | A | tst2.ts:11:11:11:11 | A | +| tst2.ts:1:8:5:1 | namespa ... lysed\\n} | tst2.ts:1:8:5:1 | A | +| tst2.ts:2:14:2:19 | x | tst2.ts:4:3:4:3 | x | +| tst2.ts:2:18:2:19 | 42 | tst2.ts:2:14:2:19 | x | +| tst2.ts:7:1:7:0 | A | tst2.ts:8:3:8:3 | A | +| tst2.ts:7:1:9:1 | functio ... = 23;\\n} | tst2.ts:7:10:7:13 | setX | +| tst2.ts:7:10:7:13 | setX | tst2.ts:3:3:3:6 | setX | +| tst2.ts:8:9:8:10 | 23 | tst2.ts:8:3:8:10 | A.x = 23 | +| tst2.ts:11:11:11:13 | A.x | tst2.ts:11:11:11:23 | A.x as number | +| tst2.ts:13:26:13:29 | List | tst2.ts:13:26:13:37 | List | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | | tst.js:1:1:1:1 | x | tst.js:28:2:28:1 | x | | tst.js:1:1:1:1 | x | tst.js:32:1:32:0 | x | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | @@ -147,17 +161,3 @@ | tst.js:111:29:111:31 | o2c | tst.js:111:6:111:38 | v2c | | tst.js:111:36:111:38 | o2d | tst.js:111:6:111:32 | [v2a, v ... = o2c] | | tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | -| tst.ts:1:1:1:1 | A | tst.ts:1:18:1:18 | A | -| tst.ts:1:1:1:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:8:5:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:8:5:1 | A | tst.ts:11:11:11:11 | A | -| tst.ts:1:8:5:1 | namespa ... lysed\\n} | tst.ts:1:8:5:1 | A | -| tst.ts:2:14:2:19 | x | tst.ts:4:3:4:3 | x | -| tst.ts:2:18:2:19 | 42 | tst.ts:2:14:2:19 | x | -| tst.ts:7:1:7:0 | A | tst.ts:8:3:8:3 | A | -| tst.ts:7:1:9:1 | functio ... = 23;\\n} | tst.ts:7:10:7:13 | setX | -| tst.ts:7:10:7:13 | setX | tst.ts:3:3:3:6 | setX | -| tst.ts:8:9:8:10 | 23 | tst.ts:8:3:8:10 | A.x = 23 | -| tst.ts:11:11:11:13 | A.x | tst.ts:11:11:11:23 | A.x as number | -| tst.ts:13:26:13:29 | List | tst.ts:13:26:13:37 | List | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | diff --git a/javascript/ql/test/library-tests/DataFlow/getIntValue.expected b/javascript/ql/test/library-tests/DataFlow/getIntValue.expected index 18ed3923069..fdeffe0b52e 100644 --- a/javascript/ql/test/library-tests/DataFlow/getIntValue.expected +++ b/javascript/ql/test/library-tests/DataFlow/getIntValue.expected @@ -1,6 +1,8 @@ | eval.js:2:11:2:12 | 42 | 42 | | sources.js:4:12:4:13 | 19 | 19 | | sources.js:5:4:5:5 | 23 | 23 | +| tst2.ts:2:18:2:19 | 42 | 42 | +| tst2.ts:8:9:8:10 | 23 | 23 | | tst.js:3:9:3:10 | 42 | 42 | | tst.js:51:11:51:12 | 42 | 42 | | tst.js:65:9:65:10 | 42 | 42 | @@ -11,5 +13,3 @@ | tst.js:103:6:103:7 | 19 | 19 | | tst.js:103:10:103:11 | 23 | 23 | | tst.js:103:14:103:14 | 0 | 0 | -| tst.ts:2:18:2:19 | 42 | 42 | -| tst.ts:8:9:8:10 | 23 | 23 | diff --git a/javascript/ql/test/library-tests/DataFlow/incomplete.expected b/javascript/ql/test/library-tests/DataFlow/incomplete.expected index 35413033fe7..040126f8c69 100644 --- a/javascript/ql/test/library-tests/DataFlow/incomplete.expected +++ b/javascript/ql/test/library-tests/DataFlow/incomplete.expected @@ -13,6 +13,18 @@ | sources.js:10:12:10:14 | key | heap | | sources.js:11:12:11:18 | key | heap | | sources.js:11:14:11:16 | key | heap | +| tst2.ts:2:14:2:19 | x | namespace | +| tst2.ts:3:3:3:8 | exceptional return of setX() | call | +| tst2.ts:3:3:3:8 | setX() | call | +| tst2.ts:7:1:9:1 | exceptional return of function setX | call | +| tst2.ts:8:3:8:5 | A.x | heap | +| tst2.ts:11:11:11:13 | A.x | heap | +| tst2.ts:13:26:13:29 | List | global | +| tst2.ts:13:39:13:38 | args | call | +| tst2.ts:13:39:13:38 | exceptional return of default constructor of class StringList | call | +| tst2.ts:13:39:13:38 | exceptional return of super(...args) | call | +| tst2.ts:13:39:13:38 | super | call | +| tst2.ts:13:39:13:38 | super(...args) | call | | tst.js:1:10:1:11 | fs | import | | tst.js:16:1:20:9 | exceptional return of (functi ... ("arg") | call | | tst.js:16:2:20:1 | exceptional return of function f | call | @@ -92,15 +104,3 @@ | tst.js:115:1:115:10 | Array.call | heap | | tst.js:115:1:115:12 | Array.call() | call | | tst.js:115:1:115:12 | exceptional return of Array.call() | call | -| tst.ts:2:14:2:19 | x | namespace | -| tst.ts:3:3:3:8 | exceptional return of setX() | call | -| tst.ts:3:3:3:8 | setX() | call | -| tst.ts:7:1:9:1 | exceptional return of function setX | call | -| tst.ts:8:3:8:5 | A.x | heap | -| tst.ts:11:11:11:13 | A.x | heap | -| tst.ts:13:26:13:29 | List | global | -| tst.ts:13:39:13:38 | args | call | -| tst.ts:13:39:13:38 | exceptional return of default constructor of class StringList | call | -| tst.ts:13:39:13:38 | exceptional return of super(...args) | call | -| tst.ts:13:39:13:38 | super | call | -| tst.ts:13:39:13:38 | super(...args) | call | diff --git a/javascript/ql/test/library-tests/DataFlow/parameters.expected b/javascript/ql/test/library-tests/DataFlow/parameters.expected index 31bab07c4e2..34cc8e6bb66 100644 --- a/javascript/ql/test/library-tests/DataFlow/parameters.expected +++ b/javascript/ql/test/library-tests/DataFlow/parameters.expected @@ -1,8 +1,8 @@ | sources.js:1:6:1:6 | x | | sources.js:3:11:3:11 | x | | sources.js:9:14:9:18 | array | +| tst2.ts:13:39:13:38 | args | | tst.js:16:13:16:13 | a | | tst.js:32:12:32:12 | b | | tst.js:87:11:87:24 | { p: x, ...o } | | tst.js:98:11:98:24 | [ x, ...rest ] | -| tst.ts:13:39:13:38 | args | diff --git a/javascript/ql/test/library-tests/DataFlow/sources.expected b/javascript/ql/test/library-tests/DataFlow/sources.expected index 37a54027371..ff60d49cf58 100644 --- a/javascript/ql/test/library-tests/DataFlow/sources.expected +++ b/javascript/ql/test/library-tests/DataFlow/sources.expected @@ -19,6 +19,18 @@ | sources.js:10:12:10:14 | key | | sources.js:11:12:11:18 | { key } | | sources.js:11:14:11:16 | key | +| tst2.ts:1:1:1:0 | this | +| tst2.ts:3:3:3:8 | setX() | +| tst2.ts:7:1:7:0 | this | +| tst2.ts:7:1:9:1 | functio ... = 23;\\n} | +| tst2.ts:8:3:8:5 | A.x | +| tst2.ts:11:11:11:13 | A.x | +| tst2.ts:13:1:13:40 | class S ... ing> {} | +| tst2.ts:13:26:13:29 | List | +| tst2.ts:13:39:13:38 | (...arg ... rgs); } | +| tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | super(...args) | +| tst2.ts:13:39:13:38 | this | | tst.js:1:1:1:0 | this | | tst.js:1:1:1:24 | import ... m 'fs'; | | tst.js:1:10:1:11 | fs | @@ -105,15 +117,3 @@ | tst.js:115:1:115:10 | Array.call | | tst.js:115:1:115:12 | Array.call() | | tst.js:115:1:115:12 | reflective call | -| tst.ts:1:1:1:0 | this | -| tst.ts:3:3:3:8 | setX() | -| tst.ts:7:1:7:0 | this | -| tst.ts:7:1:9:1 | functio ... = 23;\\n} | -| tst.ts:8:3:8:5 | A.x | -| tst.ts:11:11:11:13 | A.x | -| tst.ts:13:1:13:40 | class S ... ing> {} | -| tst.ts:13:26:13:29 | List | -| tst.ts:13:39:13:38 | (...arg ... rgs); } | -| tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | super(...args) | -| tst.ts:13:39:13:38 | this | diff --git a/javascript/ql/test/library-tests/DataFlow/tst.ts b/javascript/ql/test/library-tests/DataFlow/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/DataFlow/tst.ts rename to javascript/ql/test/library-tests/DataFlow/tst2.ts diff --git a/javascript/ql/test/library-tests/Decorators/Decoratable.expected b/javascript/ql/test/library-tests/Decorators/Decoratable.expected index 7fe95e7e08a..3f2f33e6123 100644 --- a/javascript/ql/test/library-tests/Decorators/Decoratable.expected +++ b/javascript/ql/test/library-tests/Decorators/Decoratable.expected @@ -1,15 +1,15 @@ +| tst2.ts:7:9:7:9 | a | 0 | tst2.ts:7:6:7:7 | @A | +| tst2.ts:8:12:8:13 | ab | 0 | tst2.ts:8:6:8:7 | @A | +| tst2.ts:8:12:8:13 | ab | 1 | tst2.ts:8:9:8:10 | @B | +| tst2.ts:10:15:10:15 | a | 0 | tst2.ts:10:12:10:13 | @A | +| tst2.ts:11:18:11:19 | ab | 0 | tst2.ts:11:12:11:13 | @A | +| tst2.ts:11:18:11:19 | ab | 1 | tst2.ts:11:15:11:16 | @B | +| tst2.ts:13:9:13:9 | a | 0 | tst2.ts:13:6:13:7 | @A | +| tst2.ts:13:15:13:15 | b | 0 | tst2.ts:13:12:13:13 | @B | +| tst2.ts:14:9:14:9 | a | 0 | tst2.ts:14:6:14:7 | @A | +| tst2.ts:14:18:14:19 | bc | 0 | tst2.ts:14:12:14:13 | @B | +| tst2.ts:14:18:14:19 | bc | 1 | tst2.ts:14:15:14:16 | @C | | tst.js:1:7:3:1 | class C ... ) { }\\n} | 0 | tst.js:1:1:1:2 | @A | | tst.js:1:7:3:1 | class C ... ) { }\\n} | 1 | tst.js:1:4:1:5 | @B | | tst.js:2:19:2:25 | m() { } | 0 | tst.js:2:3:2:17 | @testable(true) | | tst.js:7:3:7:25 | get bar ... rn 42 } | 0 | tst.js:6:3:6:6 | @Foo | -| tst.ts:7:9:7:9 | a | 0 | tst.ts:7:6:7:7 | @A | -| tst.ts:8:12:8:13 | ab | 0 | tst.ts:8:6:8:7 | @A | -| tst.ts:8:12:8:13 | ab | 1 | tst.ts:8:9:8:10 | @B | -| tst.ts:10:15:10:15 | a | 0 | tst.ts:10:12:10:13 | @A | -| tst.ts:11:18:11:19 | ab | 0 | tst.ts:11:12:11:13 | @A | -| tst.ts:11:18:11:19 | ab | 1 | tst.ts:11:15:11:16 | @B | -| tst.ts:13:9:13:9 | a | 0 | tst.ts:13:6:13:7 | @A | -| tst.ts:13:15:13:15 | b | 0 | tst.ts:13:12:13:13 | @B | -| tst.ts:14:9:14:9 | a | 0 | tst.ts:14:6:14:7 | @A | -| tst.ts:14:18:14:19 | bc | 0 | tst.ts:14:12:14:13 | @B | -| tst.ts:14:18:14:19 | bc | 1 | tst.ts:14:15:14:16 | @C | diff --git a/javascript/ql/test/library-tests/Decorators/Decorator.expected b/javascript/ql/test/library-tests/Decorators/Decorator.expected index 0027eebc756..70fc86830f5 100644 --- a/javascript/ql/test/library-tests/Decorators/Decorator.expected +++ b/javascript/ql/test/library-tests/Decorators/Decorator.expected @@ -1,15 +1,15 @@ +| tst2.ts:7:6:7:7 | @A | tst2.ts:7:7:7:7 | A | tst2.ts:7:9:7:9 | a | +| tst2.ts:8:6:8:7 | @A | tst2.ts:8:7:8:7 | A | tst2.ts:8:12:8:13 | ab | +| tst2.ts:8:9:8:10 | @B | tst2.ts:8:10:8:10 | B | tst2.ts:8:12:8:13 | ab | +| tst2.ts:10:12:10:13 | @A | tst2.ts:10:13:10:13 | A | tst2.ts:10:15:10:15 | a | +| tst2.ts:11:12:11:13 | @A | tst2.ts:11:13:11:13 | A | tst2.ts:11:18:11:19 | ab | +| tst2.ts:11:15:11:16 | @B | tst2.ts:11:16:11:16 | B | tst2.ts:11:18:11:19 | ab | +| tst2.ts:13:6:13:7 | @A | tst2.ts:13:7:13:7 | A | tst2.ts:13:9:13:9 | a | +| tst2.ts:13:12:13:13 | @B | tst2.ts:13:13:13:13 | B | tst2.ts:13:15:13:15 | b | +| tst2.ts:14:6:14:7 | @A | tst2.ts:14:7:14:7 | A | tst2.ts:14:9:14:9 | a | +| tst2.ts:14:12:14:13 | @B | tst2.ts:14:13:14:13 | B | tst2.ts:14:18:14:19 | bc | +| tst2.ts:14:15:14:16 | @C | tst2.ts:14:16:14:16 | C | tst2.ts:14:18:14:19 | bc | | tst.js:1:1:1:2 | @A | tst.js:1:2:1:2 | A | tst.js:1:7:3:1 | class C ... ) { }\\n} | | tst.js:1:4:1:5 | @B | tst.js:1:5:1:5 | B | tst.js:1:7:3:1 | class C ... ) { }\\n} | | tst.js:2:3:2:17 | @testable(true) | tst.js:2:4:2:17 | testable(true) | tst.js:2:19:2:25 | m() { } | | tst.js:6:3:6:6 | @Foo | tst.js:6:4:6:6 | Foo | tst.js:7:3:7:25 | get bar ... rn 42 } | -| tst.ts:7:6:7:7 | @A | tst.ts:7:7:7:7 | A | tst.ts:7:9:7:9 | a | -| tst.ts:8:6:8:7 | @A | tst.ts:8:7:8:7 | A | tst.ts:8:12:8:13 | ab | -| tst.ts:8:9:8:10 | @B | tst.ts:8:10:8:10 | B | tst.ts:8:12:8:13 | ab | -| tst.ts:10:12:10:13 | @A | tst.ts:10:13:10:13 | A | tst.ts:10:15:10:15 | a | -| tst.ts:11:12:11:13 | @A | tst.ts:11:13:11:13 | A | tst.ts:11:18:11:19 | ab | -| tst.ts:11:15:11:16 | @B | tst.ts:11:16:11:16 | B | tst.ts:11:18:11:19 | ab | -| tst.ts:13:6:13:7 | @A | tst.ts:13:7:13:7 | A | tst.ts:13:9:13:9 | a | -| tst.ts:13:12:13:13 | @B | tst.ts:13:13:13:13 | B | tst.ts:13:15:13:15 | b | -| tst.ts:14:6:14:7 | @A | tst.ts:14:7:14:7 | A | tst.ts:14:9:14:9 | a | -| tst.ts:14:12:14:13 | @B | tst.ts:14:13:14:13 | B | tst.ts:14:18:14:19 | bc | -| tst.ts:14:15:14:16 | @C | tst.ts:14:16:14:16 | C | tst.ts:14:18:14:19 | bc | diff --git a/javascript/ql/test/library-tests/Decorators/tst.ts b/javascript/ql/test/library-tests/Decorators/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/Decorators/tst.ts rename to javascript/ql/test/library-tests/Decorators/tst2.ts diff --git a/javascript/ql/test/library-tests/FileTypes/FileTypes.expected b/javascript/ql/test/library-tests/FileTypes/FileTypes.expected index 45ab1533acb..455bbdb6e33 100644 --- a/javascript/ql/test/library-tests/FileTypes/FileTypes.expected +++ b/javascript/ql/test/library-tests/FileTypes/FileTypes.expected @@ -1,14 +1,14 @@ +| jsTest.js:0:0:0:0 | jsTest.js | javascript | +| jsxTest.jsx:0:0:0:0 | jsxTest.jsx | javascript | +| mjsTest.mjs:0:0:0:0 | mjsTest.mjs | javascript | | test.htm:0:0:0:0 | test.htm | html | | test.html:0:0:0:0 | test.html | html | -| test.js:0:0:0:0 | test.js | javascript | | test.json:0:0:0:0 | test.json | json | -| test.jsx:0:0:0:0 | test.jsx | javascript | -| test.mjs:0:0:0:0 | test.mjs | javascript | | test.raml:0:0:0:0 | test.raml | yaml | -| test.ts:0:0:0:0 | test.ts | typescript | -| test.tsx:0:0:0:0 | test.tsx | typescript | | test.vue:0:0:0:0 | test.vue | html | | test.xhtm:0:0:0:0 | test.xhtm | html | | test.xhtml:0:0:0:0 | test.xhtml | html | | test.yaml:0:0:0:0 | test.yaml | yaml | | test.yml:0:0:0:0 | test.yml | yaml | +| tsTest.ts:0:0:0:0 | tsTest.ts | typescript | +| tsxTest.tsx:0:0:0:0 | tsxTest.tsx | typescript | diff --git a/javascript/ql/test/library-tests/FileTypes/test.js b/javascript/ql/test/library-tests/FileTypes/jsTest.js similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.js rename to javascript/ql/test/library-tests/FileTypes/jsTest.js diff --git a/javascript/ql/test/library-tests/FileTypes/test.jsx b/javascript/ql/test/library-tests/FileTypes/jsxTest.jsx similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.jsx rename to javascript/ql/test/library-tests/FileTypes/jsxTest.jsx diff --git a/javascript/ql/test/library-tests/FileTypes/test.mjs b/javascript/ql/test/library-tests/FileTypes/mjsTest.mjs similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.mjs rename to javascript/ql/test/library-tests/FileTypes/mjsTest.mjs diff --git a/javascript/ql/test/library-tests/FileTypes/test.ts b/javascript/ql/test/library-tests/FileTypes/tsTest.ts similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.ts rename to javascript/ql/test/library-tests/FileTypes/tsTest.ts diff --git a/javascript/ql/test/library-tests/FileTypes/test.tsx b/javascript/ql/test/library-tests/FileTypes/tsxTest.tsx similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.tsx rename to javascript/ql/test/library-tests/FileTypes/tsxTest.tsx diff --git a/javascript/ql/test/library-tests/Flow/AbstractValues.expected b/javascript/ql/test/library-tests/Flow/AbstractValues.expected index 531faf562bd..ceea3b05389 100644 --- a/javascript/ql/test/library-tests/Flow/AbstractValues.expected +++ b/javascript/ql/test/library-tests/Flow/AbstractValues.expected @@ -272,6 +272,10 @@ | ts.ts:1:16:1:25 | class A | | ts.ts:1:16:1:25 | instance of class A | | ts.ts:1:24:1:23 | default constructor of class A | +| tsTest.ts:1:1:13:0 | exports object of module tsTest | +| tsTest.ts:1:1:13:0 | module object of module tsTest | +| tsTest.ts:8:1:10:1 | function setX | +| tsTest.ts:8:1:10:1 | instance of function setX | | tst2.js:3:2:5:1 | anonymous function | | tst2.js:3:2:5:1 | instance of anonymous function | | tst.js:1:1:39:1 | arguments object of function tst | @@ -341,9 +345,5 @@ | tst.js:174:1:183:1 | function awaitFlow | | tst.mjs:1:1:4:0 | exports object of module tst | | tst.mjs:1:1:4:0 | module object of module tst | -| tst.ts:1:1:13:0 | exports object of module tst | -| tst.ts:1:1:13:0 | module object of module tst | -| tst.ts:8:1:10:1 | function setX | -| tst.ts:8:1:10:1 | instance of function setX | | with.js:1:1:17:1 | function f | | with.js:1:1:17:1 | instance of function f | diff --git a/javascript/ql/test/library-tests/Flow/abseval.expected b/javascript/ql/test/library-tests/Flow/abseval.expected index ff2ad70cdd4..ba021a2d36b 100644 --- a/javascript/ql/test/library-tests/Flow/abseval.expected +++ b/javascript/ql/test/library-tests/Flow/abseval.expected @@ -281,6 +281,10 @@ | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | file://:0:0:0:0 | "" | | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | file://:0:0:0:0 | non-empty, non-numeric string | | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | file://:0:0:0:0 | numeric string | +| tsTest.ts:2:14:2:14 | x | tsTest.ts:2:18:2:19 | 42 | file://:0:0:0:0 | non-zero value | +| tsTest.ts:4:7:4:8 | x2 | tsTest.ts:4:12:4:12 | x | file://:0:0:0:0 | indefinite value (namespace) | +| tsTest.ts:4:7:4:8 | x2 | tsTest.ts:4:12:4:12 | x | file://:0:0:0:0 | non-zero value | +| tsTest.ts:12:5:12:5 | a | tsTest.ts:12:9:12:9 | A | file://:0:0:0:0 | object | | tst2.js:4:7:4:7 | x | tst2.js:4:11:4:20 | someGlobal | file://:0:0:0:0 | "" | | tst2.js:4:7:4:7 | x | tst2.js:4:11:4:20 | someGlobal | file://:0:0:0:0 | indefinite value (global) | | tst.js:3:7:3:8 | x1 | tst.js:3:12:3:15 | true | file://:0:0:0:0 | true | @@ -462,10 +466,6 @@ | tst.js:186:5:186:6 | x1 | tst.js:186:10:186:24 | someOtherGlobal | file://:0:0:0:0 | indefinite value (global) | | tst.js:186:5:186:6 | x1 | tst.js:186:10:186:24 | someOtherGlobal | file://:0:0:0:0 | indefinite value (heap) | | tst.mjs:3:5:3:7 | req | tst.mjs:3:11:3:17 | require | file://:0:0:0:0 | indefinite value (global) | -| tst.ts:2:14:2:14 | x | tst.ts:2:18:2:19 | 42 | file://:0:0:0:0 | non-zero value | -| tst.ts:4:7:4:8 | x2 | tst.ts:4:12:4:12 | x | file://:0:0:0:0 | indefinite value (namespace) | -| tst.ts:4:7:4:8 | x2 | tst.ts:4:12:4:12 | x | file://:0:0:0:0 | non-zero value | -| tst.ts:12:5:12:5 | a | tst.ts:12:9:12:9 | A | file://:0:0:0:0 | object | | with.js:2:7:2:7 | x | with.js:2:11:2:12 | 42 | file://:0:0:0:0 | non-zero value | | with.js:2:15:2:15 | y | with.js:2:19:2:22 | null | file://:0:0:0:0 | null | | with.js:4:9:4:10 | r1 | with.js:4:14:4:14 | x | file://:0:0:0:0 | indefinite value (eval) | diff --git a/javascript/ql/test/library-tests/Flow/getAPrototype.expected b/javascript/ql/test/library-tests/Flow/getAPrototype.expected index 07ff1f76b24..438fb61fa2c 100644 --- a/javascript/ql/test/library-tests/Flow/getAPrototype.expected +++ b/javascript/ql/test/library-tests/Flow/getAPrototype.expected @@ -58,6 +58,7 @@ | refinements.js:44:3:48:3 | instance of function inner | refinements.js:44:3:48:3 | instance of function inner | | refinements.js:58:1:62:1 | instance of function f6 | refinements.js:58:1:62:1 | instance of function f6 | | ts2.ts:1:10:1:22 | instance of anonymous function | ts2.ts:1:10:1:22 | instance of anonymous function | +| tsTest.ts:8:1:10:1 | instance of function setX | tsTest.ts:8:1:10:1 | instance of function setX | | tst2.js:3:2:5:1 | instance of anonymous function | tst2.js:3:2:5:1 | instance of anonymous function | | tst.js:1:1:39:1 | instance of function tst | tst.js:1:1:39:1 | instance of function tst | | tst.js:15:12:15:23 | instance of function xd | tst.js:15:12:15:23 | instance of function xd | @@ -88,5 +89,4 @@ | tst.js:144:1:149:1 | instance of function tst3 | tst.js:144:1:149:1 | instance of function tst3 | | tst.js:151:1:162:1 | instance of function tst4 | tst.js:151:1:162:1 | instance of function tst4 | | tst.js:164:1:172:1 | instance of function tst5 | tst.js:164:1:172:1 | instance of function tst5 | -| tst.ts:8:1:10:1 | instance of function setX | tst.ts:8:1:10:1 | instance of function setX | | with.js:1:1:17:1 | instance of function f | with.js:1:1:17:1 | instance of function f | diff --git a/javascript/ql/test/library-tests/Flow/tst.ts b/javascript/ql/test/library-tests/Flow/tsTest.ts similarity index 100% rename from javascript/ql/test/library-tests/Flow/tst.ts rename to javascript/ql/test/library-tests/Flow/tsTest.ts diff --git a/javascript/ql/test/library-tests/Flow/types.expected b/javascript/ql/test/library-tests/Flow/types.expected index 9b13b469bed..1cc6a526382 100644 --- a/javascript/ql/test/library-tests/Flow/types.expected +++ b/javascript/ql/test/library-tests/Flow/types.expected @@ -156,6 +156,9 @@ | refinements.js:53:7:53:8 | x5 | refinements.js:53:12:53:12 | f | undefined | | refinements.js:55:7:55:8 | x6 | refinements.js:55:12:55:12 | f | null or undefined | | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | string | +| tsTest.ts:2:14:2:14 | x | tsTest.ts:2:18:2:19 | 42 | number | +| tsTest.ts:4:7:4:8 | x2 | tsTest.ts:4:12:4:12 | x | boolean, class, date, function, null, number, object, regular expression,string or undefined | +| tsTest.ts:12:5:12:5 | a | tsTest.ts:12:9:12:9 | A | object | | tst2.js:4:7:4:7 | x | tst2.js:4:11:4:20 | someGlobal | boolean, class, date, function, null, number, object, regular expression,string or undefined | | tst.js:3:7:3:8 | x1 | tst.js:3:12:3:15 | true | boolean | | tst.js:4:7:4:8 | x2 | tst.js:4:12:4:16 | false | boolean | @@ -239,9 +242,6 @@ | tst.js:185:5:185:21 | [someOtherGlobal] | tst.js:185:25:185:26 | [] | object | | tst.js:186:5:186:6 | x1 | tst.js:186:10:186:24 | someOtherGlobal | boolean, class, date, function, null, number, object, regular expression,string or undefined | | tst.mjs:3:5:3:7 | req | tst.mjs:3:11:3:17 | require | boolean, class, date, function, null, number, object, regular expression,string or undefined | -| tst.ts:2:14:2:14 | x | tst.ts:2:18:2:19 | 42 | number | -| tst.ts:4:7:4:8 | x2 | tst.ts:4:12:4:12 | x | boolean, class, date, function, null, number, object, regular expression,string or undefined | -| tst.ts:12:5:12:5 | a | tst.ts:12:9:12:9 | A | object | | with.js:2:7:2:7 | x | with.js:2:11:2:12 | 42 | number | | with.js:2:15:2:15 | y | with.js:2:19:2:22 | null | null | | with.js:4:9:4:10 | r1 | with.js:4:14:4:14 | x | boolean, class, date, function, null, number, object, regular expression,string or undefined | diff --git a/javascript/ql/test/library-tests/LocalObjects/tst.ts b/javascript/ql/test/library-tests/LocalObjects/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/LocalObjects/tst.ts rename to javascript/ql/test/library-tests/LocalObjects/tst2.ts diff --git a/javascript/ql/test/library-tests/NPM/Modules.expected b/javascript/ql/test/library-tests/NPM/Modules.expected index 9ce1e5fccd6..89712d4df84 100644 --- a/javascript/ql/test/library-tests/NPM/Modules.expected +++ b/javascript/ql/test/library-tests/NPM/Modules.expected @@ -1,5 +1,5 @@ | b | src/node_modules/b/lib/index.js:1:1:2:0 | | -| b | src/node_modules/b/lib/index.ts:1:1:2:0 | | +| b | src/node_modules/b/lib/util.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | | d | src/node_modules/d/main.js:1:1:2:0 | | | test-package | src/index.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected index c8fe4a8ba4b..deb13a53a50 100644 --- a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected +++ b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected @@ -1,4 +1,4 @@ -| b | src/node_modules/b/lib/index.ts:1:1:2:0 | | +| b | src/node_modules/b/lib/index.js:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | | d | src/node_modules/d/main.js:1:1:2:0 | | | test-package | src/index.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/index.ts b/javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/util.ts similarity index 100% rename from javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/index.ts rename to javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/util.ts diff --git a/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected b/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected index 417b6f66ab0..6e6606a6bec 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected +++ b/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected @@ -1,5 +1,3 @@ -| electron.d.ts:2:16:2:28 | BrowserWindow | -| electron.d.ts:3:16:3:26 | BrowserView | | electron.js:3:5:3:48 | bw | | electron.js:3:10:3:48 | new Bro ... s: {}}) | | electron.js:4:5:4:46 | bv | @@ -14,7 +12,9 @@ | electron.js:62:13:62:59 | new Bro ... 1500 }) | | electron.js:63:3:63:5 | win | | electron.js:65:18:65:20 | win | -| electron.ts:3:12:3:13 | bw | -| electron.ts:3:40:3:41 | bv | -| electron.ts:4:3:4:4 | bw | -| electron.ts:5:3:5:4 | bv | +| electronTs.d.ts:2:16:2:28 | BrowserWindow | +| electronTs.d.ts:3:16:3:26 | BrowserView | +| electronTs.ts:3:12:3:13 | bw | +| electronTs.ts:3:40:3:41 | bv | +| electronTs.ts:4:3:4:4 | bw | +| electronTs.ts:5:3:5:4 | bv | diff --git a/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected b/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected index a57fb6648fb..d40ce11bdb4 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected +++ b/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected @@ -1,5 +1,5 @@ | electron.js:39:1:39:19 | foo(bw).webContents | | electron.js:40:1:40:19 | foo(bv).webContents | | electron.js:65:18:65:32 | win.webContents | -| electron.ts:4:3:4:16 | bw.webContents | -| electron.ts:5:3:5:16 | bv.webContents | +| electronTs.ts:4:3:4:16 | bw.webContents | +| electronTs.ts:5:3:5:16 | bv.webContents | diff --git a/javascript/ql/test/library-tests/frameworks/Electron/electron.d.ts b/javascript/ql/test/library-tests/frameworks/Electron/electronTs.d.ts similarity index 100% rename from javascript/ql/test/library-tests/frameworks/Electron/electron.d.ts rename to javascript/ql/test/library-tests/frameworks/Electron/electronTs.d.ts diff --git a/javascript/ql/test/library-tests/frameworks/Electron/electron.ts b/javascript/ql/test/library-tests/frameworks/Electron/electronTs.ts similarity index 72% rename from javascript/ql/test/library-tests/frameworks/Electron/electron.ts rename to javascript/ql/test/library-tests/frameworks/Electron/electronTs.ts index a4fcd1f530f..a06802db62c 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/electron.ts +++ b/javascript/ql/test/library-tests/frameworks/Electron/electronTs.ts @@ -1,4 +1,4 @@ -/// +/// function f(bw: Electron.BrowserWindow, bv: Electron.BrowserView) { bw.webContents; diff --git a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected index 6232c852ab6..112a72c7762 100644 --- a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected +++ b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected @@ -1,4 +1,4 @@ | tst2.js:0:0:0:0 | tst2.js | +| tst3.ts:0:0:0:0 | tst3.ts | | tst.html:0:0:0:0 | tst.html | | tst.js:0:0:0:0 | tst.js | -| tst.ts:0:0:0:0 | tst.ts | diff --git a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected index afed63c473b..e21fbbc260f 100644 --- a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected +++ b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected @@ -1,4 +1,4 @@ | tst2.js:0:0:0:0 | tst2.js | 26 | +| tst3.ts:0:0:0:0 | tst3.ts | 31 | | tst.html:0:0:0:0 | tst.html | 127 | | tst.js:0:0:0:0 | tst.js | 26 | -| tst.ts:0:0:0:0 | tst.ts | 31 | diff --git a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected index 53266032907..003026d73ec 100644 --- a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected +++ b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected @@ -7,6 +7,15 @@ | tst2.js:0:0:0:0 | tst2.js | LexicalExtractor_extractTokens | | tst2.js:0:0:0:0 | tst2.js | TypeScriptASTConverter_convertAST | | tst2.js:0:0:0:0 | tst2.js | TypeScriptParser_talkToParserWrapper | +| tst3.ts:0:0:0:0 | tst3.ts | ASTExtractor_extract | +| tst3.ts:0:0:0:0 | tst3.ts | CFGExtractor_extract | +| tst3.ts:0:0:0:0 | tst3.ts | FileExtractor_extractContents | +| tst3.ts:0:0:0:0 | tst3.ts | JSExtractor_extract | +| tst3.ts:0:0:0:0 | tst3.ts | JSParser_parse | +| tst3.ts:0:0:0:0 | tst3.ts | LexicalExtractor_extractLines | +| tst3.ts:0:0:0:0 | tst3.ts | LexicalExtractor_extractTokens | +| tst3.ts:0:0:0:0 | tst3.ts | TypeScriptASTConverter_convertAST | +| tst3.ts:0:0:0:0 | tst3.ts | TypeScriptParser_talkToParserWrapper | | tst.html:0:0:0:0 | tst.html | ASTExtractor_extract | | tst.html:0:0:0:0 | tst.html | CFGExtractor_extract | | tst.html:0:0:0:0 | tst.html | FileExtractor_extractContents | @@ -25,12 +34,3 @@ | tst.js:0:0:0:0 | tst.js | LexicalExtractor_extractTokens | | tst.js:0:0:0:0 | tst.js | TypeScriptASTConverter_convertAST | | tst.js:0:0:0:0 | tst.js | TypeScriptParser_talkToParserWrapper | -| tst.ts:0:0:0:0 | tst.ts | ASTExtractor_extract | -| tst.ts:0:0:0:0 | tst.ts | CFGExtractor_extract | -| tst.ts:0:0:0:0 | tst.ts | FileExtractor_extractContents | -| tst.ts:0:0:0:0 | tst.ts | JSExtractor_extract | -| tst.ts:0:0:0:0 | tst.ts | JSParser_parse | -| tst.ts:0:0:0:0 | tst.ts | LexicalExtractor_extractLines | -| tst.ts:0:0:0:0 | tst.ts | LexicalExtractor_extractTokens | -| tst.ts:0:0:0:0 | tst.ts | TypeScriptASTConverter_convertAST | -| tst.ts:0:0:0:0 | tst.ts | TypeScriptParser_talkToParserWrapper | diff --git a/javascript/ql/test/library-tests/meta/Extraction/tst.ts b/javascript/ql/test/library-tests/meta/Extraction/tst3.ts similarity index 100% rename from javascript/ql/test/library-tests/meta/Extraction/tst.ts rename to javascript/ql/test/library-tests/meta/Extraction/tst3.ts diff --git a/javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst.ts b/javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst.ts rename to javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst2.ts diff --git a/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected b/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected index f976725b559..7bc922c7171 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected +++ b/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected @@ -1,3 +1,4 @@ +| tst2.ts:24:21:24:25 | p: 42 | Unused property p. | | tst.js:4:9:4:19 | unused1: 42 | Unused property unused1. | | tst.js:19:5:19:15 | unused9: 42 | Unused property unused9. | | tst.js:26:13:26:24 | unused11: 42 | Unused property unused11. | @@ -6,4 +7,3 @@ | tst.js:52:3:52:14 | unused14: 42 | Unused property unused14. | | tst.js:54:2:54:20 | captured14.unused14 | Unused property unused14. | | tst.js:55:2:55:20 | captured14.unused14 | Unused property unused14. | -| tst.ts:24:21:24:25 | p: 42 | Unused property p. | diff --git a/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.ts b/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.ts rename to javascript/ql/test/query-tests/Declarations/UnusedProperty/tst2.ts diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected index 672ea838983..8198d8d7c1c 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected @@ -1,6 +1,6 @@ | SuspiciousPropAccess.js:4:10:4:21 | result.value | The base expression of this property access is always undefined. | | optional-chaining.js:3:5:3:7 | a.p | The base expression of this property access is always null. | | optional-chaining.js:7:5:7:7 | b.p | The base expression of this property access is always undefined. | +| tst2.ts:19:3:19:5 | x.p | The base expression of this property access is always undefined. | | tst.js:32:32:32:38 | a(1)[0] | The base expression of this property access is always null. | -| tst.ts:19:3:19:5 | x.p | The base expression of this property access is always undefined. | | typeassertion.ts:14:3:14:9 | z.field | The base expression of this property access is always null. | diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst.ts b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst.ts rename to javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst2.ts diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index dd7f524e3bf..1cbbd9faa5a 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -1,3 +1,4 @@ +| tst2.ts:6:13:6:25 | returnsVoid() | the $@ does not return anything, yet the return value is used. | tst2.ts:1:1:1:38 | declare ... : void; | function returnsVoid | | tst.html:19:31:19:43 | addHandlers() | the $@ does not return anything, yet the return value is used. | tst.html:5:7:12:7 | functio ... } | function addHandlers | | tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | | tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | @@ -6,4 +7,3 @@ | tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 | | tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | | tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | -| tst.ts:6:13:6:25 | returnsVoid() | the $@ does not return anything, yet the return value is used. | tst.ts:1:1:1:38 | declare ... : void; | function returnsVoid | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.ts b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.ts rename to javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst2.ts From e2d2c2341ec0b661664a9ffd4df64b8c371b8487 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Mar 2020 15:38:00 +0100 Subject: [PATCH 148/459] autoformat and update expected output --- .../Promises/AdditionalPromises.expected | 1 + .../ql/test/library-tests/Promises/flow.qll | 2 +- .../library-tests/Promises/tests.expected | 179 +++++++----------- 3 files changed, 70 insertions(+), 112 deletions(-) diff --git a/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected b/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected index 1c1f14deabe..ac5e94c543d 100644 --- a/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected +++ b/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected @@ -77,3 +77,4 @@ | promises.js:62:19:62:41 | Promise ... source) | | promises.js:71:5:71:27 | Promise ... source) | | promises.js:72:5:72:41 | new Pro ... ource)) | +| promises.js:79:19:79:41 | Promise ... source) | diff --git a/javascript/ql/test/library-tests/Promises/flow.qll b/javascript/ql/test/library-tests/Promises/flow.qll index d93f08a2ec4..94c2af70674 100644 --- a/javascript/ql/test/library-tests/Promises/flow.qll +++ b/javascript/ql/test/library-tests/Promises/flow.qll @@ -36,4 +36,4 @@ query predicate exclusiveTaintFlow(DataFlow::Node source, DataFlow::Node sink) { query predicate typetrack(DataFlow::SourceNode succ, DataFlow::SourceNode pred, StepSummary summary) { succ = PromiseTypeTracking::promiseStep(pred, summary) -} \ No newline at end of file +} diff --git a/javascript/ql/test/library-tests/Promises/tests.expected b/javascript/ql/test/library-tests/Promises/tests.expected index 4cd42537f3e..44dfa0d22e2 100644 --- a/javascript/ql/test/library-tests/Promises/tests.expected +++ b/javascript/ql/test/library-tests/Promises/tests.expected @@ -222,179 +222,136 @@ flow exclusiveTaintFlow | interflow.js:3:18:3:25 | "source" | interflow.js:18:10:18:14 | error | typetrack -| additional-promises.js:3:5:3:18 | p.then(x => x) | additional-promises.js:3:12:3:12 | x | level | -| additional-promises.js:3:5:3:18 | p.then(x => x) | additional-promises.js:3:12:3:12 | x | store $PromiseResolveField$ | -| additional-promises.js:3:12:3:12 | x | additional-promises.js:2:13:2:57 | new Pin ... ct) {}) | load $PromiseResolveField$ | -| flow.js:5:7:5:14 | await p1 | flow.js:4:11:4:33 | Promise ... source) | load $PromiseResolveField$ | -| flow.js:8:7:8:14 | await p2 | flow.js:7:11:7:59 | new Pro ... ource)) | load $PromiseResolveField$ | -| flow.js:11:7:11:14 | await p3 | flow.js:10:11:10:58 | new Pro ... ource)) | load $PromiseResolveField$ | -| flow.js:15:13:15:20 | await p4 | flow.js:13:11:13:58 | new Pro ... ource)) | load $PromiseResolveField$ | -| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | level | +| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | in $PromiseResolveField$ | | flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | store $PromiseResolveField$ | | flow.js:20:31:20:31 | x | flow.js:20:2:20:24 | Promise ... source) | load $PromiseResolveField$ | -| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:36:22:41 | foo(x) | level | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:36:22:41 | foo(x) | in $PromiseResolveField$ | | flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:36:22:41 | foo(x) | store $PromiseResolveField$ | -| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:49:22:55 | sink(y) | level | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:49:22:55 | sink(y) | in $PromiseResolveField$ | | flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:49:22:55 | sink(y) | store $PromiseResolveField$ | | flow.js:22:31:22:31 | x | flow.js:22:2:22:24 | Promise ... source) | load $PromiseResolveField$ | -| flow.js:24:2:24:68 | new Pro ... ink(x)) | flow.js:24:61:24:67 | sink(x) | level | +| flow.js:24:2:24:68 | new Pro ... ink(x)) | flow.js:24:61:24:67 | sink(x) | in $PromiseResolveField$ | | flow.js:24:2:24:68 | new Pro ... ink(x)) | flow.js:24:61:24:67 | sink(x) | store $PromiseResolveField$ | | flow.js:24:56:24:56 | x | flow.js:24:2:24:49 | new Pro ... ource)) | load $PromiseResolveField$ | -| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:61:26:66 | foo(x) | level | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:61:26:66 | foo(x) | in $PromiseResolveField$ | | flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:61:26:66 | foo(x) | store $PromiseResolveField$ | -| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:74:26:80 | sink(y) | level | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:74:26:80 | sink(y) | in $PromiseResolveField$ | | flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:74:26:80 | sink(y) | store $PromiseResolveField$ | | flow.js:26:56:26:56 | x | flow.js:26:2:26:49 | new Pro ... ource)) | load $PromiseResolveField$ | -| flow.js:28:2:28:60 | Promise ... ink(z)) | flow.js:28:53:28:59 | sink(z) | level | +| flow.js:28:2:28:60 | Promise ... ink(z)) | flow.js:28:53:28:59 | sink(z) | in $PromiseResolveField$ | | flow.js:28:2:28:60 | Promise ... ink(z)) | flow.js:28:53:28:59 | sink(z) | store $PromiseResolveField$ | | flow.js:28:30:28:30 | x | flow.js:28:2:28:23 | Promise ... ("foo") | load $PromiseResolveField$ | | flow.js:28:48:28:48 | z | flow.js:28:2:28:41 | Promise ... source) | load $PromiseResolveField$ | -| flow.js:30:2:30:60 | Promise ... ink(z)) | flow.js:30:53:30:59 | sink(z) | level | +| flow.js:30:2:30:60 | Promise ... ink(z)) | flow.js:30:53:30:59 | sink(z) | in $PromiseResolveField$ | | flow.js:30:2:30:60 | Promise ... ink(z)) | flow.js:30:53:30:59 | sink(z) | store $PromiseResolveField$ | | flow.js:30:31:30:31 | x | flow.js:30:2:30:24 | Promise ... source) | load $PromiseResolveField$ | | flow.js:30:48:30:48 | z | flow.js:30:2:30:41 | Promise ... "foo") | load $PromiseResolveField$ | -| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:2:32:49 | new Pro ... ource)) | level | -| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:62:32:68 | sink(x) | level | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:2:32:49 | new Pro ... ource)) | in $PromiseResolveField$ | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:62:32:68 | sink(x) | in $PromiseResolveField$ | | flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:62:32:68 | sink(x) | store $PromiseResolveField$ | -| flow.js:34:2:34:41 | Promise ... => { }) | flow.js:34:2:34:24 | Promise ... source) | level | -| flow.js:34:2:34:60 | Promise ... ink(a)) | flow.js:34:53:34:59 | sink(a) | level | +| flow.js:34:2:34:41 | Promise ... => { }) | flow.js:34:2:34:24 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:34:2:34:60 | Promise ... ink(a)) | flow.js:34:53:34:59 | sink(a) | in $PromiseResolveField$ | | flow.js:34:2:34:60 | Promise ... ink(a)) | flow.js:34:53:34:59 | sink(a) | store $PromiseResolveField$ | | flow.js:34:48:34:48 | a | flow.js:34:2:34:41 | Promise ... => { }) | load $PromiseResolveField$ | -| flow.js:37:11:37:29 | p5.catch(() => { }) | flow.js:36:11:36:33 | Promise ... source) | level | -| flow.js:38:11:38:31 | p6.then ... ink(a)) | flow.js:38:24:38:30 | sink(a) | level | +| flow.js:37:11:37:29 | p5.catch(() => { }) | flow.js:36:11:36:33 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:38:11:38:31 | p6.then ... ink(a)) | flow.js:38:24:38:30 | sink(a) | in $PromiseResolveField$ | | flow.js:38:11:38:31 | p6.then ... ink(a)) | flow.js:38:24:38:30 | sink(a) | store $PromiseResolveField$ | -| flow.js:38:19:38:19 | a | flow.js:37:11:37:29 | p5.catch(() => { }) | load $PromiseResolveField$ | -| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:2:40:65 | new Pro ... => { }) | level | -| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:78:40:84 | sink(x) | level | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:2:40:65 | new Pro ... => { }) | in $PromiseResolveField$ | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:78:40:84 | sink(x) | in $PromiseResolveField$ | | flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:78:40:84 | sink(x) | store $PromiseResolveField$ | -| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:2:42:76 | new Pro ... => { }) | level | -| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:89:42:95 | sink(x) | level | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:2:42:76 | new Pro ... => { }) | in $PromiseResolveField$ | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:89:42:95 | sink(x) | in $PromiseResolveField$ | | flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:89:42:95 | sink(x) | store $PromiseResolveField$ | -| flow.js:44:2:44:41 | Promise ... => { }) | flow.js:44:2:44:24 | Promise ... source) | level | -| flow.js:44:2:44:58 | Promise ... => { }) | flow.js:44:2:44:41 | Promise ... => { }) | level | -| flow.js:44:2:44:75 | Promise ... => { }) | flow.js:44:2:44:58 | Promise ... => { }) | level | -| flow.js:44:2:44:94 | Promise ... ink(a)) | flow.js:44:87:44:93 | sink(a) | level | +| flow.js:44:2:44:41 | Promise ... => { }) | flow.js:44:2:44:24 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:44:2:44:58 | Promise ... => { }) | flow.js:44:2:44:41 | Promise ... => { }) | in $PromiseResolveField$ | +| flow.js:44:2:44:75 | Promise ... => { }) | flow.js:44:2:44:58 | Promise ... => { }) | in $PromiseResolveField$ | +| flow.js:44:2:44:94 | Promise ... ink(a)) | flow.js:44:87:44:93 | sink(a) | in $PromiseResolveField$ | | flow.js:44:2:44:94 | Promise ... ink(a)) | flow.js:44:87:44:93 | sink(a) | store $PromiseResolveField$ | | flow.js:44:82:44:82 | a | flow.js:44:2:44:75 | Promise ... => { }) | load $PromiseResolveField$ | -| flow.js:46:2:46:43 | Promise ... => { }) | flow.js:46:2:46:24 | Promise ... source) | level | -| flow.js:46:2:46:62 | Promise ... ink(a)) | flow.js:46:55:46:61 | sink(a) | level | +| flow.js:46:2:46:43 | Promise ... => { }) | flow.js:46:2:46:24 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:46:2:46:62 | Promise ... ink(a)) | flow.js:46:55:46:61 | sink(a) | in $PromiseResolveField$ | | flow.js:46:2:46:62 | Promise ... ink(a)) | flow.js:46:55:46:61 | sink(a) | store $PromiseResolveField$ | | flow.js:46:50:46:50 | a | flow.js:46:2:46:43 | Promise ... => { }) | load $PromiseResolveField$ | -| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:2:48:36 | new Pro ... urce }) | level | -| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:49:48:55 | sink(x) | level | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:2:48:36 | new Pro ... urce }) | in $PromiseResolveField$ | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:49:48:55 | sink(x) | in $PromiseResolveField$ | | flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:49:48:55 | sink(x) | store $PromiseResolveField$ | -| flow.js:51:10:51:29 | Promise.resolve(src) | flow.js:50:25:50:27 | src | level | -| flow.js:51:10:51:29 | Promise.resolve(src) | flow.js:50:25:50:27 | src | store $PromiseResolveField$ | -| flow.js:53:2:53:41 | createP ... ink(v)) | flow.js:53:34:53:40 | sink(v) | level | +| flow.js:53:2:53:41 | createP ... ink(v)) | flow.js:53:34:53:40 | sink(v) | in $PromiseResolveField$ | | flow.js:53:2:53:41 | createP ... ink(v)) | flow.js:53:34:53:40 | sink(v) | store $PromiseResolveField$ | | flow.js:53:29:53:29 | v | flow.js:53:2:53:22 | createP ... source) | load $PromiseResolveField$ | -| flow.js:57:12:57:31 | p9.finally(() => {}) | flow.js:56:11:56:27 | p8.then(() => {}) | level | -| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:57:12:57:31 | p9.finally(() => {}) | level | -| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:58:19:58:25 | sink(x) | level | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:57:12:57:31 | p9.finally(() => {}) | in $PromiseResolveField$ | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:58:19:58:25 | sink(x) | in $PromiseResolveField$ | | flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:58:19:58:25 | sink(x) | store $PromiseResolveField$ | -| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:61:12:61:29 | p11.then(() => {}) | level | -| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | level | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:61:12:61:29 | p11.then(() => {}) | in $PromiseResolveField$ | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | in $PromiseResolveField$ | | flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | store $PromiseResolveField$ | | flow.js:65:3:65:56 | await n ... ource)) | flow.js:65:9:65:56 | new Pro ... ource)) | load $PromiseResolveField$ | -| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:2:76:32 | chained ... => {}) | level | -| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | level | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:2:76:32 | chained ... => {}) | in $PromiseResolveField$ | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | in $PromiseResolveField$ | | flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | store $PromiseResolveField$ | -| flow.js:79:3:79:22 | p.then(x => sink(x)) | flow.js:79:15:79:21 | sink(x) | level | +| flow.js:79:3:79:22 | p.then(x => sink(x)) | flow.js:79:15:79:21 | sink(x) | in $PromiseResolveField$ | | flow.js:79:3:79:22 | p.then(x => sink(x)) | flow.js:79:15:79:21 | sink(x) | store $PromiseResolveField$ | -| flow.js:79:10:79:10 | x | flow.js:78:32:78:32 | p | load $PromiseResolveField$ | -| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:83:32:83:32 | p | level | -| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:84:16:84:22 | sink(e) | level | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:83:32:83:32 | p | in $PromiseResolveField$ | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:84:16:84:22 | sink(e) | in $PromiseResolveField$ | | flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:84:16:84:22 | sink(e) | store $PromiseResolveField$ | -| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:3:89:27 | ("foo", ... => {}) | level | -| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:40:89:46 | sink(e) | level | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:3:89:27 | ("foo", ... => {}) | in $PromiseResolveField$ | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:40:89:46 | sink(e) | in $PromiseResolveField$ | | flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:40:89:46 | sink(e) | store $PromiseResolveField$ | -| flow.js:95:4:95:10 | await p | flow.js:93:33:93:33 | p | load $PromiseResolveField$ | -| flow.js:103:2:103:76 | new Pro ... ource}) | flow.js:103:2:103:48 | new Pro ... "BLA")) | level | -| flow.js:103:2:103:95 | new Pro ... ink(x)) | flow.js:103:88:103:94 | sink(x) | level | +| flow.js:103:2:103:76 | new Pro ... ource}) | flow.js:103:2:103:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:103:2:103:95 | new Pro ... ink(x)) | flow.js:103:88:103:94 | sink(x) | in $PromiseResolveField$ | | flow.js:103:2:103:95 | new Pro ... ink(x)) | flow.js:103:88:103:94 | sink(x) | store $PromiseResolveField$ | | flow.js:103:83:103:83 | x | flow.js:103:2:103:76 | new Pro ... ource}) | load $PromiseResolveField$ | -| flow.js:105:2:105:77 | new Pro ... ource}) | flow.js:105:2:105:48 | new Pro ... "BLA")) | level | -| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:2:105:77 | new Pro ... ource}) | level | -| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:90:105:96 | sink(x) | level | +| flow.js:105:2:105:77 | new Pro ... ource}) | flow.js:105:2:105:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:2:105:77 | new Pro ... ource}) | in $PromiseResolveField$ | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:90:105:96 | sink(x) | in $PromiseResolveField$ | | flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:90:105:96 | sink(x) | store $PromiseResolveField$ | -| flow.js:109:2:109:71 | new Pro ... jected) | flow.js:109:2:109:48 | new Pro ... "BLA")) | level | -| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:2:109:71 | new Pro ... jected) | level | -| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:84:109:90 | sink(x) | level | +| flow.js:109:2:109:71 | new Pro ... jected) | flow.js:109:2:109:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:2:109:71 | new Pro ... jected) | in $PromiseResolveField$ | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:84:109:90 | sink(x) | in $PromiseResolveField$ | | flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:84:109:90 | sink(x) | store $PromiseResolveField$ | -| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | -| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | -| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:111:2:111:48 | new Pro ... "BLA")) | level | -| flow.js:111:2:111:88 | new Pro ... ink(x)) | flow.js:111:81:111:87 | sink(x) | level | +| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:111:2:111:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:111:2:111:88 | new Pro ... ink(x)) | flow.js:111:81:111:87 | sink(x) | in $PromiseResolveField$ | | flow.js:111:2:111:88 | new Pro ... ink(x)) | flow.js:111:81:111:87 | sink(x) | store $PromiseResolveField$ | | flow.js:111:76:111:76 | x | flow.js:111:2:111:69 | new Pro ... jected) | load $PromiseResolveField$ | -| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | -| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | -| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:113:2:113:48 | new Pro ... "BLA")) | level | -| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:2:113:69 | new Pro ... jected) | level | -| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:82:113:88 | sink(x) | level | +| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:113:2:113:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:2:113:69 | new Pro ... jected) | in $PromiseResolveField$ | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:82:113:88 | sink(x) | in $PromiseResolveField$ | | flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:82:113:88 | sink(x) | store $PromiseResolveField$ | -| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | -| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | -| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:117:2:117:48 | new Pro ... "BLA")) | level | -| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:2:117:69 | new Pro ... solved) | level | -| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:82:117:88 | sink(x) | level | +| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:117:2:117:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:2:117:69 | new Pro ... solved) | in $PromiseResolveField$ | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:82:117:88 | sink(x) | in $PromiseResolveField$ | | flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:82:117:88 | sink(x) | store $PromiseResolveField$ | -| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | -| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | -| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:119:2:119:48 | new Pro ... "BLA")) | level | -| flow.js:119:2:119:88 | new Pro ... ink(x)) | flow.js:119:81:119:87 | sink(x) | level | +| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:119:2:119:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:119:2:119:88 | new Pro ... ink(x)) | flow.js:119:81:119:87 | sink(x) | in $PromiseResolveField$ | | flow.js:119:2:119:88 | new Pro ... ink(x)) | flow.js:119:81:119:87 | sink(x) | store $PromiseResolveField$ | | flow.js:119:76:119:76 | x | flow.js:119:2:119:69 | new Pro ... solved) | load $PromiseResolveField$ | -| flow.js:121:2:121:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | -| flow.js:121:2:121:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | -| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:2:121:41 | Promise ... solved) | level | -| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:54:121:60 | sink(x) | level | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:2:121:41 | Promise ... solved) | in $PromiseResolveField$ | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:54:121:60 | sink(x) | in $PromiseResolveField$ | | flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:54:121:60 | sink(x) | store $PromiseResolveField$ | | flow.js:121:28:121:28 | x | flow.js:121:2:121:21 | Promise.resolve(123) | load $PromiseResolveField$ | -| flow.js:123:2:123:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | -| flow.js:123:2:123:41 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | -| flow.js:123:2:123:60 | Promise ... ink(x)) | flow.js:123:53:123:59 | sink(x) | level | +| flow.js:123:2:123:60 | Promise ... ink(x)) | flow.js:123:53:123:59 | sink(x) | in $PromiseResolveField$ | | flow.js:123:2:123:60 | Promise ... ink(x)) | flow.js:123:53:123:59 | sink(x) | store $PromiseResolveField$ | | flow.js:123:28:123:28 | x | flow.js:123:2:123:21 | Promise.resolve(123) | load $PromiseResolveField$ | | flow.js:123:48:123:48 | x | flow.js:123:2:123:41 | Promise ... solved) | load $PromiseResolveField$ | -| flow.js:125:2:125:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | -| flow.js:125:2:125:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | -| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:2:125:41 | Promise ... jected) | level | -| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:54:125:60 | sink(x) | level | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:2:125:41 | Promise ... jected) | in $PromiseResolveField$ | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:54:125:60 | sink(x) | in $PromiseResolveField$ | | flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:54:125:60 | sink(x) | store $PromiseResolveField$ | | flow.js:125:28:125:28 | x | flow.js:125:2:125:21 | Promise.resolve(123) | load $PromiseResolveField$ | -| flow.js:127:2:127:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | level | -| flow.js:127:2:127:41 | Promise ... jected) | flow.js:107:17:107:64 | new Pro ... ource)) | store $PromiseResolveField$ | -| flow.js:127:2:127:60 | Promise ... ink(x)) | flow.js:127:53:127:59 | sink(x) | level | +| flow.js:127:2:127:60 | Promise ... ink(x)) | flow.js:127:53:127:59 | sink(x) | in $PromiseResolveField$ | | flow.js:127:2:127:60 | Promise ... ink(x)) | flow.js:127:53:127:59 | sink(x) | store $PromiseResolveField$ | | flow.js:127:28:127:28 | x | flow.js:127:2:127:21 | Promise.resolve(123) | load $PromiseResolveField$ | | flow.js:127:48:127:48 | x | flow.js:127:2:127:41 | Promise ... jected) | load $PromiseResolveField$ | -| flow.js:129:2:129:52 | new Pro ... olved)) | flow.js:115:17:115:39 | Promise ... source) | level | -| flow.js:129:2:129:52 | new Pro ... olved)) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | -| flow.js:129:2:129:71 | new Pro ... ink(x)) | flow.js:129:64:129:70 | sink(x) | level | +| flow.js:129:2:129:71 | new Pro ... ink(x)) | flow.js:129:64:129:70 | sink(x) | in $PromiseResolveField$ | | flow.js:129:2:129:71 | new Pro ... ink(x)) | flow.js:129:64:129:70 | sink(x) | store $PromiseResolveField$ | | flow.js:129:59:129:59 | x | flow.js:129:2:129:52 | new Pro ... olved)) | load $PromiseResolveField$ | -| flow.js:131:2:131:26 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | level | -| flow.js:131:2:131:26 | Promise ... solved) | flow.js:115:17:115:39 | Promise ... source) | store $PromiseResolveField$ | -| flow.js:131:2:131:45 | Promise ... ink(x)) | flow.js:131:38:131:44 | sink(x) | level | +| flow.js:131:2:131:45 | Promise ... ink(x)) | flow.js:131:38:131:44 | sink(x) | in $PromiseResolveField$ | | flow.js:131:2:131:45 | Promise ... ink(x)) | flow.js:131:38:131:44 | sink(x) | store $PromiseResolveField$ | | flow.js:131:33:131:33 | x | flow.js:131:2:131:26 | Promise ... solved) | load $PromiseResolveField$ | -| interflow.js:6:3:9:23 | loadScr ... eError) | interflow.js:6:3:8:26 | loadScr ... () { }) | level | -| promises.js:6:26:6:28 | val | promises.js:3:17:5:4 | new Pro ... );\\n }) | load $PromiseResolveField$ | -| promises.js:18:18:18:18 | v | promises.js:10:18:17:4 | new Pro ... );\\n }) | load $PromiseResolveField$ | -| promises.js:23:3:25:4 | promise ... v;\\n }) | promises.js:10:18:17:4 | new Pro ... );\\n }) | level | -| promises.js:26:3:28:4 | promise ... v;\\n }) | promises.js:10:18:17:4 | new Pro ... );\\n }) | level | -| promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:34:17:34:22 | source | level | +| interflow.js:6:3:9:23 | loadScr ... eError) | interflow.js:6:3:8:26 | loadScr ... () { }) | in $PromiseResolveField$ | +| promises.js:23:3:25:4 | promise ... v;\\n }) | promises.js:10:18:17:4 | new Pro ... );\\n }) | in $PromiseResolveField$ | +| promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:34:17:34:22 | source | in $PromiseResolveField$ | | promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:34:17:34:22 | source | store $PromiseResolveField$ | -| promises.js:36:28:36:30 | val | promises.js:33:19:35:6 | new Pro ... \\n }) | load $PromiseResolveField$ | -| promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:44:17:44:22 | source | level | +| promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:44:17:44:22 | source | in $PromiseResolveField$ | | promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:44:17:44:22 | source | store $PromiseResolveField$ | -| promises.js:46:28:46:30 | val | promises.js:43:19:45:6 | Q.Promi ... \\n }) | load $PromiseResolveField$ | -| promises.js:54:28:54:30 | val | promises.js:53:19:53:41 | Promise ... source) | load $PromiseResolveField$ | -| promises.js:63:28:63:30 | val | promises.js:62:19:62:41 | Promise ... source) | load $PromiseResolveField$ | | promises.js:71:34:71:36 | val | promises.js:71:5:71:27 | Promise ... source) | load $PromiseResolveField$ | | promises.js:72:48:72:50 | val | promises.js:72:5:72:41 | new Pro ... ource)) | load $PromiseResolveField$ | | promises.js:75:27:75:29 | val | promises.js:75:5:75:20 | resolver.promise | load $PromiseResolveField$ | -| promises.js:79:19:79:41 | Promise ... source) | promises.js:78:11:78:16 | source | level | -| promises.js:79:19:79:41 | Promise ... source) | promises.js:78:11:78:16 | source | store $PromiseResolveField$ | -| promises.js:80:28:80:30 | val | promises.js:79:19:79:41 | Promise ... source) | load $PromiseResolveField$ | From a850616927062df3e84e7c10a21e8c859bc6b33e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Mar 2020 15:40:37 +0100 Subject: [PATCH 149/459] delete Xss.actual --- javascript/ql/src/Security/CWE-079/Xss.actual | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 javascript/ql/src/Security/CWE-079/Xss.actual diff --git a/javascript/ql/src/Security/CWE-079/Xss.actual b/javascript/ql/src/Security/CWE-079/Xss.actual deleted file mode 100644 index ac992895b9c..00000000000 --- a/javascript/ql/src/Security/CWE-079/Xss.actual +++ /dev/null @@ -1,3 +0,0 @@ -nodes -edges -#select From 6b507c6933c15afbcb50f50e26fe625ef386df02 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Mar 2020 15:47:59 +0100 Subject: [PATCH 150/459] add urlSuffix support to DomBasedXSS --- .../security/dataflow/DomBasedXss.qll | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll index deca4bd3db4..e190ccf735c 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll @@ -23,5 +23,33 @@ module DomBasedXss { or node instanceof Sanitizer } + + override predicate isAdditionalLoadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string predProp, string succProp + ) { + exists(DataFlow::PropRead read | + pred = read.getBase() and + succ = read and + read.getPropertyName() = "hash" and + predProp = "hash" and + succProp = urlSuffixPseudoProperty() + ) + } + + override predicate isAdditionalLoadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + exists(DataFlow::MethodCallNode call, string name | + name = "substr" or name = "substring" or name = "slice" + | + call.getMethodName() = name and + not call.getArgument(0).getIntValue() = 0 and + pred = call.getReceiver() and + succ = call and + prop = urlSuffixPseudoProperty() + ) + } + } + + private string urlSuffixPseudoProperty() { + result = "$UrlSuffix$" } } From 71e0dc087b7da56b0d10c373332c72726760795e Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Thu, 26 Mar 2020 15:35:31 +0000 Subject: [PATCH 151/459] C#: General code tidy. --- .../BuildAnalysis.cs | 55 ++- .../CsProjFile.cs | 77 +--- .../DotNet.cs | 2 +- .../DotNetRuntimeInfo.cs | 132 ------- .../MSBuildHelper.cs | 260 ------------- .../NugetPackageRepository.cs | 357 ------------------ .../NugetPackages.cs | 45 +++ .../Program.cs | 10 - .../ProgressMonitor.cs | 33 +- ...Semmle.Extraction.CSharp.Standalone.csproj | 5 +- .../SolutionFile.cs | 3 +- .../Entities/NamespaceDeclaration.cs | 3 +- .../extractor/Semmle.Extraction/Extractor.cs | 4 +- 13 files changed, 87 insertions(+), 899 deletions(-) delete mode 100644 csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs delete mode 100644 csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs delete mode 100644 csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs index dfc110c0d03..5ec150e5af3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs @@ -2,11 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; -using Semmle.Util; using Semmle.Extraction.CSharp.Standalone; using System.Threading.Tasks; -using System.Collections.Concurrent; namespace Semmle.BuildAnalyser { @@ -47,18 +44,18 @@ namespace Semmle.BuildAnalyser /// class BuildAnalysis : IBuildAnalysis { - readonly AssemblyCache assemblyCache; - readonly NugetPackages nuget; - readonly IProgressMonitor progressMonitor; - HashSet usedReferences = new HashSet(); - readonly HashSet usedSources = new HashSet(); - readonly HashSet missingSources = new HashSet(); - readonly Dictionary unresolvedReferences = new Dictionary(); - readonly DirectoryInfo sourceDir; - int failedProjects, succeededProjects; - readonly string[] allSources; - int conflictedReferences = 0; - object mutex = new object(); + private readonly AssemblyCache assemblyCache; + private readonly NugetPackages nuget; + private readonly IProgressMonitor progressMonitor; + private HashSet usedReferences = new HashSet(); + private readonly HashSet usedSources = new HashSet(); + private readonly HashSet missingSources = new HashSet(); + private readonly Dictionary unresolvedReferences = new Dictionary(); + private readonly DirectoryInfo sourceDir; + private int failedProjects, succeededProjects; + private readonly string[] allSources; + private int conflictedReferences = 0; + private readonly object mutex = new object(); /// /// Performs a C# build analysis. @@ -80,7 +77,7 @@ namespace Semmle.BuildAnalyser ToArray(); var dllDirNames = options.DllDirs.Select(Path.GetFullPath).ToList(); - PackageDirectory = TemporaryDirectory.CreateTempDirectory(sourceDir.FullName, progressMonitor); + PackageDirectory = TemporaryDirectory.CreateTempDirectory(sourceDir.FullName); if (options.UseNuGet) { @@ -102,6 +99,7 @@ namespace Semmle.BuildAnalyser } { + // These files can sometimes prevent `dotnet restore` from working correctly. using var renamer1 = new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories)); using var renamer2 = new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories)); @@ -118,12 +116,6 @@ namespace Semmle.BuildAnalyser usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); } - if (!options.AnalyseCsProjFiles) - { - usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); - } - - ResolveConflicts(); if (options.UseMscorlib) @@ -150,9 +142,8 @@ namespace Semmle.BuildAnalyser UnresolvedReferences.Count(), conflictedReferences, succeededProjects + failedProjects, - failedProjects); - - Console.WriteLine($"Build analysis completed in {DateTime.Now - startTime}"); + failedProjects, + DateTime.Now - startTime); } /// @@ -285,7 +276,7 @@ namespace Semmle.BuildAnalyser try { - var csProj = new CsProjFile(project); + IProjectFile csProj = new CsProjFile(project); foreach (var @ref in csProj.References) { @@ -329,8 +320,16 @@ namespace Semmle.BuildAnalyser void Restore(string projectOrSolution) { int exit = DotNet.RestoreToDirectory(projectOrSolution, PackageDirectory.DirInfo.FullName); - if (exit != 0) - progressMonitor.CommandFailed("dotnet", $"restore \"{projectOrSolution}\"", exit); + switch(exit) + { + case 0: + case 1: + // No errors + break; + default: + progressMonitor.CommandFailed("dotnet", $"restore \"{projectOrSolution}\"", exit); + break; + } } public void RestoreSolutions(IEnumerable solutions) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs index 02391c6eb7c..7394eddb39c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs @@ -5,84 +5,17 @@ using System.Xml; namespace Semmle.BuildAnalyser { - /// - /// A reference to a particular version of a particular package. - /// - class PackageReference - { - public PackageReference(string include, string version) { - Include = include; - Version = version; - } - public string Include, Version; - - public override string ToString() => $"Include={Include}, Version={Version}"; - } - - enum ProjectFileType - { - MsBuildProject, - DotNetProject, - OtherProject - } - interface IProjectFile { - IEnumerable ProjectReferences { get; } - - IEnumerable Packages { get; } - IEnumerable References { get; } - IEnumerable Sources { get; } - - IEnumerable TargetFrameworks { get; } - } - - class NetCoreProjectFile : IProjectFile - { - FileInfo path; - XmlDocument doc; - XmlElement root; - - public NetCoreProjectFile(FileInfo path) - { - this.path = path; - doc = new XmlDocument(); - doc.Load(path.FullName); - root = doc.DocumentElement; - } - - public IEnumerable ProjectReferences => throw new System.NotImplementedException(); - - public IEnumerable Packages - { - get - { - var packages = root.SelectNodes("/Project/ItemGroup/PackageReference"); - return packages.NodeList(). - Select(r => - new PackageReference(r.Attributes.GetNamedItem("Include").Value, r.Attributes.GetNamedItem("Version").Value)); - } - } - - public IEnumerable References => throw new System.NotImplementedException(); - - public IEnumerable Sources - { - get - { - return path.Directory.GetFiles("*.cs", SearchOption.AllDirectories); - } - } - - public IEnumerable TargetFrameworks => throw new System.NotImplementedException(); + IEnumerable Sources { get; } } /// /// Represents a .csproj file and reads information from it. /// - class CsProjFile + class CsProjFile : IProjectFile { public string Filename { get; } @@ -136,8 +69,6 @@ namespace Semmle.BuildAnalyser .ToArray(); } - string[] targetFrameworks = new string[0]; - /// /// Reads the .csproj file directly as XML. /// This doesn't handle variables etc, and should only used as a @@ -162,8 +93,6 @@ namespace Semmle.BuildAnalyser var frameworksNode = root.SelectNodes("/Project/PropertyGroup/TargetFrameworks").NodeList().Concat( root.SelectNodes("/Project/PropertyGroup/TargetFramework").NodeList()).Select(node => node.InnerText); - targetFrameworks = frameworksNode.SelectMany(node => node.Split(";")).ToArray(); - var relativeCsIncludes2 = root.SelectNodes("/Project/ItemGroup/Compile/@Include", mgr). NodeList(). @@ -208,8 +137,6 @@ namespace Semmle.BuildAnalyser /// public IEnumerable References => references; - public IEnumerable TargetFrameworks => targetFrameworks; - /// /// The list of C# source files in full path format. /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs index 6d36892c7c9..4aad28068b0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs @@ -22,7 +22,7 @@ namespace Semmle.BuildAnalyser /// /// Utility to temporarily rename a set of files. /// - class FileRenamer : IDisposable + sealed class FileRenamer : IDisposable { string[] files; const string suffix = ".codeqlhidden"; diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs deleted file mode 100644 index 21fe4a22338..00000000000 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNetRuntimeInfo.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Diagnostics; - -namespace RoslynWS -{ - /// - /// Information about the .NET Core runtime. - /// - public class DotNetRuntimeInfo - { - /// - /// A cache of .NET runtime information by target directory. - /// - static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); - - /// - /// The .NET Core version. - /// - public string Version { get; set; } - - /// - /// The .NET Core base directory. - /// - public string BaseDirectory { get; set; } - - /// - /// The current runtime identifier (RID). - /// - public string RID { get; set; } - - /// - /// Get information about the current .NET Core runtime. - /// - /// - /// An optional base directory where dotnet.exe should be run (this may affect the version it reports due to global.json). - /// - /// - /// A containing the runtime information. - /// - public static DotNetRuntimeInfo GetCurrent(string baseDirectory = null) - { - return _cache.GetOrAdd(baseDirectory, _ => - { - DotNetRuntimeInfo runtimeInfo = new DotNetRuntimeInfo(); - - Process dotnetInfoProcess = Process.Start(new ProcessStartInfo - { - FileName = "dotnet", - WorkingDirectory = baseDirectory, - Arguments = "--info", - UseShellExecute = false, - RedirectStandardOutput = true - }); - using (dotnetInfoProcess) - { - dotnetInfoProcess.WaitForExit(); - - string currentSection = null; - string currentLine; - while ((currentLine = dotnetInfoProcess.StandardOutput.ReadLine()) != null) - { - if (String.IsNullOrWhiteSpace(currentLine)) - continue; - - if (!currentLine.StartsWith(" ")) - { - currentSection = currentLine; - - continue; - } - - string[] property = currentLine.Split(new char[] { ':' }, count: 2); - if (property.Length != 2) - continue; - - property[0] = property[0].Trim(); - property[1] = property[1].Trim(); - - switch (currentSection) - { - case "Product Information:": - { - switch (property[0]) - { - case "Version": - { - runtimeInfo.Version = property[1]; - - break; - } - } - - break; - } - case "Runtime Environment:": - { - switch (property[0]) - { - case "Base Path": - { - runtimeInfo.BaseDirectory = property[1]; - - break; - } - case "RID": - { - runtimeInfo.RID = property[1]; - - break; - } - } - - break; - } - } - } - } - - return runtimeInfo; - }); - } - - /// - /// Clear the cache of .NET runtime information. - /// - public static void ClearCache() - { - _cache.Clear(); - } - } -} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs deleted file mode 100644 index cbba36e8419..00000000000 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/MSBuildHelper.cs +++ /dev/null @@ -1,260 +0,0 @@ - -using Microsoft.Build.Construction; -using Microsoft.Build.Evaluation; -using Microsoft.Build.Exceptions; -using System; -using System.Collections.Generic; -using System.IO; -using System.Collections.Immutable; - -namespace RoslynWS -{ - /// - /// Helper methods for working with MSBuild projects. - /// - public static class MSBuildHelper - { - /// - /// The names of well-known item metadata. - /// - public static readonly ImmutableSortedSet WellknownMetadataNames = - ImmutableSortedSet.Create( - "FullPath", - "RootDir", - "Filename", - "Extension", - "RelativeDir", - "Directory", - "RecursiveDir", - "Identity", - "ModifiedTime", - "CreatedTime", - "AccessedTime" - ); - - /// - /// Create an MSBuild project collection. - /// - /// - /// The base (i.e. solution) directory. - /// - /// - /// The project collection. - /// - public static ProjectCollection CreateProjectCollection(string solutionDirectory) - { - return CreateProjectCollection(solutionDirectory, - DotNetRuntimeInfo.GetCurrent(solutionDirectory) - ); - } - - /// - /// Create an MSBuild project collection. - /// - /// - /// The base (i.e. solution) directory. - /// - /// - /// Information about the current .NET Core runtime. - /// - /// - /// The project collection. - /// - public static ProjectCollection CreateProjectCollection(string solutionDirectory, DotNetRuntimeInfo runtimeInfo) - { - if (String.IsNullOrWhiteSpace(solutionDirectory)) - throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'baseDir'.", nameof(solutionDirectory)); - - if (runtimeInfo == null) - throw new ArgumentNullException(nameof(runtimeInfo)); - - if (String.IsNullOrWhiteSpace(runtimeInfo.BaseDirectory)) - throw new InvalidOperationException("Cannot determine base directory for .NET Core."); - - Dictionary globalProperties = CreateGlobalMSBuildProperties(runtimeInfo, solutionDirectory); - EnsureMSBuildEnvironment(globalProperties); - - ProjectCollection projectCollection = new ProjectCollection(globalProperties) { IsBuildEnabled = false }; - - // Override toolset paths (for some reason these point to the main directory where the dotnet executable lives). - Toolset toolset = projectCollection.GetToolset("15.0"); - toolset = new Toolset( - toolsVersion: "15.0", - toolsPath: globalProperties["MSBuildExtensionsPath"], - projectCollection: projectCollection, - msbuildOverrideTasksPath: "" - ); - projectCollection.AddToolset(toolset); - - return projectCollection; - } - - /// - /// Create global properties for MSBuild. - /// - /// - /// Information about the current .NET Core runtime. - /// - /// - /// The base (i.e. solution) directory. - /// - /// - /// A dictionary containing the global properties. - /// - public static Dictionary CreateGlobalMSBuildProperties(DotNetRuntimeInfo runtimeInfo, string solutionDirectory) - { - if (runtimeInfo == null) - throw new ArgumentNullException(nameof(runtimeInfo)); - - if (String.IsNullOrWhiteSpace(solutionDirectory)) - throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'solutionDirectory'.", nameof(solutionDirectory)); - - if (solutionDirectory.Length > 0 && solutionDirectory[solutionDirectory.Length - 1] != Path.DirectorySeparatorChar) - solutionDirectory += Path.DirectorySeparatorChar; - - return new Dictionary - { - [WellKnownPropertyNames.DesignTimeBuild] = "true", - [WellKnownPropertyNames.BuildProjectReferences] = "false", - [WellKnownPropertyNames.ResolveReferenceDependencies] = "true", - [WellKnownPropertyNames.SolutionDir] = solutionDirectory, - [WellKnownPropertyNames.MSBuildExtensionsPath] = runtimeInfo.BaseDirectory, - [WellKnownPropertyNames.MSBuildSDKsPath] = Path.Combine(runtimeInfo.BaseDirectory, "Sdks"), - [WellKnownPropertyNames.RoslynTargetsPath] = Path.Combine(runtimeInfo.BaseDirectory, "Roslyn") - }; - } - - /// - /// Ensure that environment variables are populated using the specified MSBuild global properties. - /// - /// - /// The MSBuild global properties - /// - public static void EnsureMSBuildEnvironment(Dictionary globalMSBuildProperties) - { - if (globalMSBuildProperties == null) - throw new ArgumentNullException(nameof(globalMSBuildProperties)); - - // Kinda sucks that the simplest way to get MSBuild to resolve SDKs correctly is using environment variables, but there you go. - Environment.SetEnvironmentVariable( - WellKnownPropertyNames.MSBuildExtensionsPath, - globalMSBuildProperties[WellKnownPropertyNames.MSBuildExtensionsPath] - ); - Environment.SetEnvironmentVariable( - WellKnownPropertyNames.MSBuildSDKsPath, - globalMSBuildProperties[WellKnownPropertyNames.MSBuildSDKsPath] - ); - } - - /// - /// Does the specified property name represent a private property? - /// - /// - /// The property name. - /// - /// - /// true, if the property name starts with an underscore; otherwise, false. - /// - public static bool IsPrivateProperty(string propertyName) => propertyName?.StartsWith("_") ?? false; - - /// - /// Does the specified metadata name represent a private property? - /// - /// - /// The metadata name. - /// - /// - /// true, if the metadata name starts with an underscore; otherwise, false. - /// - public static bool IsPrivateMetadata(string metadataName) => metadataName?.StartsWith("_") ?? false; - - /// - /// Does the specified item type represent a private property? - /// - /// - /// The item type. - /// - /// - /// true, if the item type starts with an underscore; otherwise, false. - /// - public static bool IsPrivateItemType(string itemType) => itemType?.StartsWith("_") ?? false; - - /// - /// Determine whether the specified metadata name represents well-known (built-in) item metadata. - /// - /// - /// The metadata name. - /// - /// - /// true, if represents well-known item metadata; otherwise, false. - /// - public static bool IsWellKnownItemMetadata(string metadataName) => WellknownMetadataNames.Contains(metadataName); - - /// - /// Create a copy of the project for caching. - /// - /// - /// The MSBuild project. - /// - /// - /// The project copy (independent of original, but sharing the same ). - /// - /// - /// You can only create a single cached copy for a given project. - /// - public static Project CloneAsCachedProject(this Project project) - { - if (project == null) - throw new ArgumentNullException(nameof(project)); - - ProjectRootElement clonedXml = project.Xml.DeepClone(); - Project clonedProject = new Project(clonedXml, project.GlobalProperties, project.ToolsVersion, project.ProjectCollection); - clonedProject.FullPath = Path.ChangeExtension(project.FullPath, - ".cached" + Path.GetExtension(project.FullPath) - ); - - return clonedProject; - } - - /// - /// The names of well-known MSBuild properties. - /// - public static class WellKnownPropertyNames - { - /// - /// The "MSBuildExtensionsPath" property. - /// - public static readonly string MSBuildExtensionsPath = "MSBuildExtensionsPath"; - - /// - /// The "MSBuildSDKsPath" property. - /// - public static readonly string MSBuildSDKsPath = "MSBuildSDKsPath"; - - /// - /// The "SolutionDir" property. - /// - public static readonly string SolutionDir = "SolutionDir"; - - /// - /// The "_ResolveReferenceDependencies" property. - /// - public static readonly string ResolveReferenceDependencies = "_ResolveReferenceDependencies"; - - /// - /// The "DesignTimeBuild" property. - /// - public static readonly string DesignTimeBuild = "DesignTimeBuild"; - - /// - /// The "BuildProjectReferences" property. - /// - public static readonly string BuildProjectReferences = "BuildProjectReferences"; - - /// - /// The "RoslynTargetsPath" property. - /// - public static readonly string RoslynTargetsPath = "RoslynTargetsPath"; - } - } -} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs deleted file mode 100644 index 3b84df7463c..00000000000 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackageRepository.cs +++ /dev/null @@ -1,357 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; - -namespace Semmle.BuildAnalyser -{ - /// - /// A package in a NuGet package repository. - /// For example, the directory C:\Users\calum\.nuget\packages\microsoft.visualbasic. - /// - /// Each package contains a number of subdirectories, organised by version. - /// - class Package - { - public readonly string directory; - - /// - /// Constructs a package for the given directory. - /// - /// The directory. - public Package(string dir) - { - directory = dir; - } - - /// - /// The name of the package. - /// - public string Name => Path.GetDirectoryName(directory); - - /// - /// The versions that exist within the package. - /// - public IEnumerable Versions => Directory.GetDirectories(directory).Select(dir => new PackageVersion(dir)); - - public override string ToString() => Path.GetFileName(directory); - - public PackageVersion FindVersion(string version) - { - if (Directory.Exists(Path.Combine(directory, version))) - return new PackageVersion(Path.Combine(directory, version)); - else - return Versions.OrderByDescending(v => v.Version).First(); - } - - /// - /// Locates the exact version of a particular package. - /// - /// The version to locate. - /// The specific version of the package. - public PackageVersion FindExactVersion(string version) - { - if (Directory.Exists(Path.Combine(directory, version))) - return new PackageVersion(Path.Combine(directory, version)); - else - return null; - } - } - - /// - /// A package in a NuGet package respository, including the specific version. - /// For example, the directory C:\Users\calum\.nuget\packages\microsoft.visualbasic\10.0.1 - /// - class PackageVersion - { - readonly string directory; - - /// - /// The version of the package. - /// - public string Version => Path.GetFileName(directory); - - /// - /// Constructs a package version from its directory. - /// - /// The directory of this package. - public PackageVersion(string directory) - { - if (!Directory.Exists(directory)) - throw new DirectoryNotFoundException(directory); - - this.directory = directory; - } - - public override string ToString() => Version; - - /// - /// The frameworks within this package. - /// Sometimes a directory references several frameworks, for example - /// "net451+netstandard2.0". This are split into separate frameworks. - /// - IEnumerable UnorderedFrameworks - { - get - { - return UnorderedFrameworksInDirectory(Path.Combine(directory, "lib")). - Concat(UnorderedFrameworksInDirectory(Path.Combine(directory, "ref"))). - Concat(UnorderedFrameworksInDirectory(Path.Combine(directory, "build", "lib"))). - Concat(UnorderedFrameworksInDirectory(Path.Combine(directory, "build", "ref"))). - Concat(TryDirectory(Path.Combine(directory, "lib"))); - } - } - - IEnumerable TryDirectory(string directory) - { - if (Directory.Exists(directory)) - yield return new PackageFramework(directory, "unknown"); - } - - IEnumerable UnorderedFrameworksInDirectory(string lib) - { - if (!Directory.Exists(lib)) - yield break; - foreach (var p in System.IO.Directory.GetDirectories(lib)) - { - var name = Path.GetFileName(p); - if (name.Contains('+')) - { - foreach (var p2 in name.Split('+')) - yield return new PackageFramework(p, p2); - } - else - yield return new PackageFramework(p, name); - } - } - - /// - /// The frameworks in this package, in a consistent sequence, with the "best" frameworks - /// appearing at the start of the list. - /// - /// Priorities "netstandard" framework, followed by "netcoreapp", followed by everything else. - /// Then, selects the highest version number. - /// - public IEnumerable Frameworks => - UnorderedFrameworks. - OrderBy(framework => framework.Framework.StartsWith("netstandard") ? 0 : framework.Framework.StartsWith("netcoreapp") ? 1 : 2). - ThenByDescending(framework => framework.Framework); - - /// - /// Finds the best framework containing references. - /// Returns null if no suitable framework was found. - /// - public PackageFramework? BestFramework => Frameworks.Where(f => f.References.Any()).FirstOrDefault(); - - public bool ContainsLibraries - { - get - { - return Directory.Exists(Path.Combine(directory, "lib")) || - Directory.Exists(Path.Combine(directory, "ref")) || - Directory.Exists(Path.Combine(directory, "build", "lib")) || - Directory.Exists(Path.Combine(directory, "build", "ref")); - } - } - - public bool ContainsDLLs - { - get - { - return Directory.GetFiles(directory, "*.dll", SearchOption.AllDirectories).Any(); - } - } - } - - /// - /// A framework in a package. - /// For example, C:\Users\calum\.nuget\packages\microsoft.testplatform.objectmodel\16.4.0\lib\netstandard2.0 - /// - class PackageFramework - { - public string Directory { get; } - - /// - /// The framework name. - /// - public string Framework { get; } - - /// - /// Constructs a package framework from a directory. - /// The framework is needed because the directory may specify more than one framework. - /// - /// The directory path. - /// The framework. - public PackageFramework(string dir, string framework) - { - if (!System.IO.Directory.Exists(dir)) - throw new FileNotFoundException(dir); - Directory = dir; - Framework = framework; - } - - /// - /// The reference DLLs contained within the directory. - /// - public IEnumerable References - { - get - { - return new DirectoryInfo(Directory).GetFiles("*.dll").Select(fi => fi.FullName); - } - } - - public override string ToString() => Directory; - } - - class TemporaryDirectory : IDisposable - { - readonly IProgressMonitor ProgressMonitor; - - public DirectoryInfo DirInfo { get; } - - public TemporaryDirectory(string name, IProgressMonitor pm) - { - ProgressMonitor = pm; - DirInfo = new DirectoryInfo(name); - DirInfo.Create(); - } - - /// - /// Computes a unique temp directory for the packages associated - /// with this source tree. Use a SHA1 of the directory name. - /// - /// - /// The full path of the temp directory. - public static string ComputeTempDirectory(string srcDir) - { - var bytes = Encoding.Unicode.GetBytes(srcDir); - - var sha1 = new SHA1CryptoServiceProvider(); - var sha = sha1.ComputeHash(bytes); - var sb = new StringBuilder(); - foreach (var b in sha.Take(8)) - sb.AppendFormat("{0:x2}", b); - - return Path.Combine(Path.GetTempPath(), "GitHub", "packages", sb.ToString()); - } - - public static TemporaryDirectory CreateTempDirectory(string source, IProgressMonitor pm) => new TemporaryDirectory(ComputeTempDirectory(source), pm); - - public void Cleanup() - { - try - { - DirInfo.Delete(true); - } - catch (System.IO.IOException ex) - { - ProgressMonitor.Warning(string.Format("Couldn't delete package directory - it's probably held open by something else: {0}", ex.Message)); - } - - } - - public void Dispose() - { - Cleanup(); - } - - public override string ToString() => DirInfo.FullName.ToString(); - } - - /// - /// The NuGet package repository. - /// - class NugetPackageRepository - { - // A list of package directories, in the order they should be searched. - private readonly string[] packageDirs; - - public NugetPackageRepository(params string[] dirs) - { - packageDirs = dirs; - } - - /// - /// Constructs a NuGet package repository, using the default locations. - /// For example, - /// $HOME/.nuget/packages, /usr/share/dotnet/sdk/NuGetFallbackFolder - /// - public NugetPackageRepository(string sourceDir) - { - var homeFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - var nugetPackages = Path.Combine(homeFolder, ".nuget", "packages"); - var nugetFallbackFolder = Environment.OSVersion.Platform == PlatformID.Win32NT ? - @"C:\Program Files\dotnet\sdk\NuGetFallbackFolder" : - "/usr/share/dotnet/sdk/NuGetFallbackFolder"; - - packageDirs = new string[] { nugetPackages, nugetFallbackFolder }; - } - - /// - /// Enumerate all available packages. - /// - public IEnumerable Packages - { - get - { - foreach (var d in packageDirs) - foreach (var p in Directory.GetDirectories(d)) - { - var name = Path.GetFileName(p); - if (!name.StartsWith('.')) - yield return new Package(p); - } - } - } - - /// - /// Tries to find a PackageFramework directory for a given package reference. - /// - /// The package reference to search for. - /// The package that was found. - /// True if a package/version/framework was found. - public bool TryFindLibs(PackageReference reference, out PackageFramework package, out ResolutionFailureReason reason) - { - var packages = packageDirs. - Where(d => Directory.Exists(Path.Combine(d, reference.Include.ToLowerInvariant()))). - Select(d => new Package(Path.Combine(d, reference.Include.ToLowerInvariant()))); - - if(!packages.Any()) - { - reason = ResolutionFailureReason.PackageNotFound; - package = null; - return false; - } - - var version = packages.Select(p => p.FindVersion(reference.Version)).FirstOrDefault(v => !(v is null)); - - if (version is null) - { - reason = ResolutionFailureReason.VersionNotFound; - package = null; - return false; - } - - package = version.BestFramework; - if(package is null) - { - reason = ResolutionFailureReason.LibsNotFound; - return false; - } - - reason = ResolutionFailureReason.Success; - return true; - } - } - - enum ResolutionFailureReason - { - Success, - PackageNotFound, - VersionNotFound, - LibsNotFound - } -} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs index 0fc207f2049..dade3909635 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs @@ -135,4 +135,49 @@ namespace Semmle.BuildAnalyser readonly string nugetExe; } + + sealed class TemporaryDirectory : IDisposable + { + public DirectoryInfo DirInfo { get; } + + public TemporaryDirectory(string name) + { + DirInfo = new DirectoryInfo(name); + DirInfo.Create(); + } + + /// + /// Computes a unique temp directory for the packages associated + /// with this source tree. Use a SHA1 of the directory name. + /// + /// + /// The full path of the temp directory. + public static string ComputeTempDirectory(string srcDir) + { + var bytes = Encoding.Unicode.GetBytes(srcDir); + + var sha1 = new SHA1CryptoServiceProvider(); + var sha = sha1.ComputeHash(bytes); + var sb = new StringBuilder(); + foreach (var b in sha.Take(8)) + sb.AppendFormat("{0:x2}", b); + + return Path.Combine(Path.GetTempPath(), "GitHub", "packages", sb.ToString()); + } + + public static TemporaryDirectory CreateTempDirectory(string source) => new TemporaryDirectory(ComputeTempDirectory(source)); + + public void Cleanup() + { + DirInfo.Delete(true); + } + + public void Dispose() + { + Cleanup(); + } + + public override string ToString() => DirInfo.FullName.ToString(); + } + } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs index 3ba368f6da0..75c2bf31e6d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs @@ -3,11 +3,6 @@ using System.Collections.Generic; using System.Linq; using Semmle.BuildAnalyser; using Semmle.Util.Logging; -using System.IO; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; - -// using Microsoft.Build.Locator; namespace Semmle.Extraction.CSharp.Standalone { @@ -87,11 +82,6 @@ namespace Semmle.Extraction.CSharp.Standalone public class Program { - void LoadSolutionFile(string file) - { - - } - static int Main(string[] args) { var options = Options.Create(args); diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs index a004e59eb13..03815f7f710 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs @@ -1,4 +1,5 @@ using Semmle.Util.Logging; +using System; namespace Semmle.BuildAnalyser { @@ -9,19 +10,15 @@ namespace Semmle.BuildAnalyser { void FindingFiles(string dir); void UnresolvedReference(string id, string project); - void AnalysingProjectFiles(int count); void AnalysingSolution(string filename); void FailedProjectFile(string filename, string reason); void FailedNugetCommand(string exe, string args, string message); void NugetInstall(string package); void ResolvedReference(string filename); - void Summary(int existingSources, int usedSources, int missingSources, int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects); + void Summary(int existingSources, int usedSources, int missingSources, int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects, TimeSpan analysisTime); void Warning(string message); void ResolvedConflict(string asm1, string asm2); void MissingProject(string projectFile); - void Restored(string line); - void MissingPackage(string package, string version, ResolutionFailureReason reason); - void FoundPackage(string package, string version, string directory); void CommandFailed(string exe, string arguments, int exitCode); void MissingNuGet(); } @@ -52,11 +49,6 @@ namespace Semmle.BuildAnalyser logger.Log(Severity.Debug, "Unresolved {0} referenced by {1}", id, project); } - public void AnalysingProjectFiles(int count) - { - logger.Log(Severity.Info, "Analyzing project files..."); - } - public void AnalysingSolution(string filename) { logger.Log(Severity.Info, $"Analysing {filename}..."); @@ -85,7 +77,8 @@ namespace Semmle.BuildAnalyser public void Summary(int existingSources, int usedSources, int missingSources, int references, int unresolvedReferences, - int resolvedConflicts, int totalProjects, int failedProjects) + int resolvedConflicts, int totalProjects, int failedProjects, + TimeSpan analysisTime) { logger.Log(Severity.Info, ""); logger.Log(Severity.Info, "Build analysis summary:"); @@ -97,23 +90,7 @@ namespace Semmle.BuildAnalyser logger.Log(Severity.Info, "{0, 6} resolved assembly conflicts", resolvedConflicts); logger.Log(Severity.Info, "{0, 6} projects", totalProjects); logger.Log(Severity.Info, "{0, 6} missing/failed projects", failedProjects); - } - - public void Restored(string line) - { - logger.Log(Severity.Debug, $" {line}"); - } - - private static string[] reasonText = { "success", "package was not found", "the version was not found", "the package does not appear to contain any libraries" }; - - public void MissingPackage(string package, string version, ResolutionFailureReason reason) - { - logger.Log(Severity.Info, $" Couldn't find package {package} {version} because {reasonText[(int)reason]}"); - } - - public void FoundPackage(string package, string version, string directory) - { - logger.Log(Severity.Debug, $" Found package {package} {version} in {directory}"); + logger.Log(Severity.Info, "Build analysis completed in {0}", analysisTime); } public void Warning(string message) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj index 1d4ab57d2d8..b8c27e49e8d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj @@ -21,10 +21,7 @@ - - - - + diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs index ffaebe360fe..b4551dd8024 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs @@ -11,7 +11,8 @@ namespace Semmle.BuildAnalyser class SolutionFile { readonly Microsoft.Build.Construction.SolutionFile solutionFile; - public string FullPath { get; } + + private string FullPath { get; } /// /// Read the file. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs index a0dd41aaafb..7a14bb719fc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs @@ -23,7 +23,8 @@ namespace Semmle.Extraction.CSharp.Entities protected override void Populate(TextWriter trapFile) { - var ns = Namespace.Create(cx, (INamespaceSymbol)cx.GetModel(Node).GetSymbolInfo(Node.Name).Symbol); + var @namespace = (INamespaceSymbol) cx.GetModel(Node).GetSymbolInfo(Node.Name).Symbol; + var ns = Namespace.Create(cx, @namespace); trapFile.namespace_declarations(this, ns); trapFile.namespace_declaration_location(this, cx.Create(Node.Name.GetLocation())); diff --git a/csharp/extractor/Semmle.Extraction/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor.cs index e1ca23f645b..13750c1aa5c 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor.cs @@ -50,14 +50,14 @@ namespace Semmle.Extraction /// Record a new error type. /// /// The display name of the type, qualified where possible. - /// The missing type was referenced from a source file. + /// If the missing type was referenced from a source file. void MissingType(string fqn, bool fromSource); /// /// Record an unresolved `using namespace` directive. /// /// The full name of the namespace. - /// The missing namespace was referenced from a source file. + /// If the missing namespace was referenced from a source file. void MissingNamespace(string fqn, bool fromSource); /// From 8a968dac815a020d0937596ebaa14d32a11bf4d4 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Thu, 26 Mar 2020 20:10:21 +0000 Subject: [PATCH 152/459] C#: Enable nullability in Semmle.Util --- csharp/extractor/Semmle.Util/ActionMap.cs | 9 ++++----- csharp/extractor/Semmle.Util/CanonicalPathCache.cs | 11 ++++++----- .../extractor/Semmle.Util/CommandLineExtensions.cs | 2 +- .../extractor/Semmle.Util/DictionaryExtensions.cs | 5 ++--- csharp/extractor/Semmle.Util/FileUtils.cs | 2 +- csharp/extractor/Semmle.Util/FuzzyDictionary.cs | 13 ++++++------- .../extractor/Semmle.Util/IEnumerableExtensions.cs | 2 +- csharp/extractor/Semmle.Util/LineCounter.cs | 4 ++-- csharp/extractor/Semmle.Util/Logger.cs | 4 ++-- csharp/extractor/Semmle.Util/LoggerUtils.cs | 6 +++--- .../Semmle.Util/ProcessStartInfoExtensions.cs | 2 +- csharp/extractor/Semmle.Util/Semmle.Util.csproj | 1 + csharp/extractor/Semmle.Util/SharedReference.cs | 2 +- 13 files changed, 31 insertions(+), 32 deletions(-) diff --git a/csharp/extractor/Semmle.Util/ActionMap.cs b/csharp/extractor/Semmle.Util/ActionMap.cs index 019410be7b2..c9fecbf9da6 100644 --- a/csharp/extractor/Semmle.Util/ActionMap.cs +++ b/csharp/extractor/Semmle.Util/ActionMap.cs @@ -9,20 +9,19 @@ namespace Semmle.Util /// /// /// - public class ActionMap + public class ActionMap where Key : notnull { public void Add(Key key, Value value) { - Action a; - if (actions.TryGetValue(key, out a)) + + if (actions.TryGetValue(key, out var a)) a(value); values[key] = value; } public void OnAdd(Key key, Action action) { - Action a; - if (actions.TryGetValue(key, out a)) + if (actions.TryGetValue(key, out var a)) { actions[key] = a + action; } diff --git a/csharp/extractor/Semmle.Util/CanonicalPathCache.cs b/csharp/extractor/Semmle.Util/CanonicalPathCache.cs index 3610bb0d46e..8e86907bf0a 100644 --- a/csharp/extractor/Semmle.Util/CanonicalPathCache.cs +++ b/csharp/extractor/Semmle.Util/CanonicalPathCache.cs @@ -127,8 +127,8 @@ namespace Semmle.Util if (parent != null) { - string name = Path.GetFileName(path); - string parentPath = cache.GetCanonicalPath(parent.FullName); + string? name = Path.GetFileName(path); + string? parentPath = cache.GetCanonicalPath(parent.FullName); try { string[] entries = Directory.GetFileSystemEntries(parentPath, name); @@ -313,14 +313,15 @@ namespace Semmle.Util /// The canonical path. public string GetCanonicalPath(string path) { - string canonicalPath; lock (cache) - if (!cache.TryGetValue(path, out canonicalPath)) + { + if (!cache.TryGetValue(path, out var canonicalPath)) { canonicalPath = pathStrategy.GetCanonicalPath(path, this); AddToCache(path, canonicalPath); } - return canonicalPath; + return canonicalPath; + } } } } diff --git a/csharp/extractor/Semmle.Util/CommandLineExtensions.cs b/csharp/extractor/Semmle.Util/CommandLineExtensions.cs index b7c5166f2f0..01a581d612d 100644 --- a/csharp/extractor/Semmle.Util/CommandLineExtensions.cs +++ b/csharp/extractor/Semmle.Util/CommandLineExtensions.cs @@ -18,7 +18,7 @@ namespace Semmle.Util var found = false; foreach (var arg in commandLineArguments.Where(arg => arg.StartsWith('@')).Select(arg => arg.Substring(1))) { - string line; + string? line; using (StreamReader file = new StreamReader(arg)) while ((line = file.ReadLine()) != null) textWriter.WriteLine(line); diff --git a/csharp/extractor/Semmle.Util/DictionaryExtensions.cs b/csharp/extractor/Semmle.Util/DictionaryExtensions.cs index 7a15ce10c92..bb0d732a17f 100644 --- a/csharp/extractor/Semmle.Util/DictionaryExtensions.cs +++ b/csharp/extractor/Semmle.Util/DictionaryExtensions.cs @@ -9,10 +9,9 @@ namespace Semmle.Util /// dictionary. If a list does not already exist, a new list is /// created. /// - public static void AddAnother(this Dictionary> dict, T1 key, T2 element) + public static void AddAnother(this Dictionary> dict, T1 key, T2 element) where T1:notnull { - List list; - if (!dict.TryGetValue(key, out list)) + if (!dict.TryGetValue(key, out var list)) { list = new List(); dict[key] = list; diff --git a/csharp/extractor/Semmle.Util/FileUtils.cs b/csharp/extractor/Semmle.Util/FileUtils.cs index e5f10a18521..32e2ed88e60 100644 --- a/csharp/extractor/Semmle.Util/FileUtils.cs +++ b/csharp/extractor/Semmle.Util/FileUtils.cs @@ -62,7 +62,7 @@ namespace Semmle.Util /// /// Returns null of no path can be found. /// - public static string FindProgramOnPath(string prog) + public static string? FindProgramOnPath(string prog) { var paths = Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator); string[] exes; diff --git a/csharp/extractor/Semmle.Util/FuzzyDictionary.cs b/csharp/extractor/Semmle.Util/FuzzyDictionary.cs index a00d75fbbe5..6f364904b06 100644 --- a/csharp/extractor/Semmle.Util/FuzzyDictionary.cs +++ b/csharp/extractor/Semmle.Util/FuzzyDictionary.cs @@ -37,7 +37,7 @@ namespace Semmle.Util /// /// /// The value type. - public class FuzzyDictionary + public class FuzzyDictionary where T:class { // All data items indexed by the "base string" (stripped of numbers) readonly Dictionary>> index = new Dictionary>>(); @@ -61,7 +61,7 @@ namespace Semmle.Util /// Vector 1 /// Vector 2 /// The Hamming Distance. - static int HammingDistance(IEnumerable v1, IEnumerable v2) + static int HammingDistance(IEnumerable v1, IEnumerable v2) where U: notnull { return v1.Zip(v2, (x, y) => x.Equals(y) ? 0 : 1).Sum(); } @@ -72,11 +72,10 @@ namespace Semmle.Util /// The query string. /// The distance between the query string and the stored string. /// The best match, or null (default). - public T FindMatch(string query, out int distance) + public T? FindMatch(string query, out int distance) { string root = StripDigits(query); - List> list; - if (!index.TryGetValue(root, out list)) + if (!index.TryGetValue(root, out var list)) { distance = 0; return default(T); @@ -93,9 +92,9 @@ namespace Semmle.Util /// The distance function. /// The distance between the query and the stored string. /// The stored value. - static T BestMatch(string query, IEnumerable> candidates, Func distance, out int bestDistance) + static T? BestMatch(string query, IEnumerable> candidates, Func distance, out int bestDistance) { - T bestMatch = default(T); + T? bestMatch = default(T); bestDistance = 0; bool first = true; diff --git a/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs b/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs index d53fcf99ff4..7665dedfa70 100644 --- a/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs +++ b/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs @@ -93,7 +93,7 @@ namespace Semmle.Util /// The type of the item. /// The list of items to hash. /// The hash code. - public static int SequenceHash(this IEnumerable items) + public static int SequenceHash(this IEnumerable items) where T: notnull { int h = 0; foreach (var i in items) diff --git a/csharp/extractor/Semmle.Util/LineCounter.cs b/csharp/extractor/Semmle.Util/LineCounter.cs index c122d5865be..f4f6758a250 100644 --- a/csharp/extractor/Semmle.Util/LineCounter.cs +++ b/csharp/extractor/Semmle.Util/LineCounter.cs @@ -31,9 +31,9 @@ namespace Semmle.Util //#################### PUBLIC METHODS #################### #region - public override bool Equals(Object other) + public override bool Equals(object? other) { - LineCounts rhs = other as LineCounts; + var rhs = other as LineCounts; return rhs != null && Total == rhs.Total && Code == rhs.Code && Comment == rhs.Comment; } diff --git a/csharp/extractor/Semmle.Util/Logger.cs b/csharp/extractor/Semmle.Util/Logger.cs index d6405724734..cd353bd4f0f 100644 --- a/csharp/extractor/Semmle.Util/Logger.cs +++ b/csharp/extractor/Semmle.Util/Logger.cs @@ -67,8 +67,8 @@ namespace Semmle.Util.Logging try { - var dir = Path.GetDirectoryName(outputFile); - if (dir.Length > 0 && !System.IO.Directory.Exists(dir)) + string? dir = Path.GetDirectoryName(outputFile); + if (!string.IsNullOrEmpty(dir) && !System.IO.Directory.Exists(dir)) Directory.CreateDirectory(dir); writer = new PidStreamWriter(new FileStream(outputFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 8192)); diff --git a/csharp/extractor/Semmle.Util/LoggerUtils.cs b/csharp/extractor/Semmle.Util/LoggerUtils.cs index 39a40c37158..d94ff6f189f 100644 --- a/csharp/extractor/Semmle.Util/LoggerUtils.cs +++ b/csharp/extractor/Semmle.Util/LoggerUtils.cs @@ -21,7 +21,7 @@ namespace Semmle.Util private readonly string prefix = "[" + Process.GetCurrentProcess().Id + "] "; - public override void WriteLine(string value) + public override void WriteLine(string? value) { lock (mutex) { @@ -29,9 +29,9 @@ namespace Semmle.Util } } - public override void WriteLine(string value, object[] args) + public override void WriteLine(string? value, object?[] args) { - WriteLine(String.Format(value, args)); + WriteLine(value is null ? value : String.Format(value, args)); } readonly object mutex = new object(); diff --git a/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs b/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs index 0d9d6b04a13..5252372a58b 100644 --- a/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs +++ b/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs @@ -14,7 +14,7 @@ namespace Semmle.Util stdout = new List(); using (var process = Process.Start(pi)) { - string s; + string? s; do { s = process.StandardOutput.ReadLine(); diff --git a/csharp/extractor/Semmle.Util/Semmle.Util.csproj b/csharp/extractor/Semmle.Util/Semmle.Util.csproj index 4ef3eda35d9..39f0c7cdedb 100644 --- a/csharp/extractor/Semmle.Util/Semmle.Util.csproj +++ b/csharp/extractor/Semmle.Util/Semmle.Util.csproj @@ -6,6 +6,7 @@ Semmle.Util false win-x64;linux-x64;osx-x64 + enable diff --git a/csharp/extractor/Semmle.Util/SharedReference.cs b/csharp/extractor/Semmle.Util/SharedReference.cs index 6870c5acb35..ba87caeefaa 100644 --- a/csharp/extractor/Semmle.Util/SharedReference.cs +++ b/csharp/extractor/Semmle.Util/SharedReference.cs @@ -13,6 +13,6 @@ namespace Semmle.Util /// /// The shared object to which different parts of the code want to refer. /// - public T Obj { get; set; } + public T? Obj { get; set; } } } From b94b4b7c9132d6ef0a01a66f04a3c94daec2482b Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Thu, 26 Mar 2020 17:57:14 +0000 Subject: [PATCH 153/459] C#: Fix tests --- .../BuildAnalysis.cs | 26 +++++++++---------- .../CsProjFile.cs | 3 --- .../DotNet.cs | 2 +- .../NugetPackages.cs | 23 +++++++++------- .../Program.cs | 2 +- .../SymbolExtensions.cs | 1 - .../src/semmle/code/csharp/exprs/Access.qll | 7 ++++- .../standalone/controlflow/cfg.expected | 17 ++++++++---- .../errorrecovery/ErrorCalls.expected | 2 +- .../standalone/regressions/ConstCase.expected | 5 ++-- .../standalone/regressions/ConstCase.ql | 4 +-- 11 files changed, 51 insertions(+), 41 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs index 5ec150e5af3..cdbc0315726 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs @@ -100,20 +100,20 @@ namespace Semmle.BuildAnalyser { // These files can sometimes prevent `dotnet restore` from working correctly. - using var renamer1 = new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories)); - using var renamer2 = new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories)); + using (new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories))) + using (new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories))) + { + var solutions = options.SolutionFile != null ? + new[] { options.SolutionFile } : + sourceDir.GetFiles("*.sln", SearchOption.AllDirectories).Select(d => d.FullName); - var solutions = options.SolutionFile != null ? - new[] { options.SolutionFile } : - sourceDir.GetFiles("*.sln", SearchOption.AllDirectories).Select(d => d.FullName); + RestoreSolutions(solutions); + dllDirNames.Add(PackageDirectory.DirInfo.FullName); + assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); + AnalyseSolutions(solutions); - - RestoreSolutions(solutions); - dllDirNames.Add(PackageDirectory.DirInfo.FullName); - assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); - AnalyseSolutions(solutions); - - usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); + usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); + } } ResolveConflicts(); @@ -254,7 +254,7 @@ namespace Semmle.BuildAnalyser unresolvedReferences[id] = projectFile; } - TemporaryDirectory PackageDirectory; + readonly TemporaryDirectory PackageDirectory; /// /// Reads all the source files and references from the given list of projects. diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs index 7394eddb39c..fc7972b6169 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs @@ -90,9 +90,6 @@ namespace Semmle.BuildAnalyser if(netCoreProjectFile) { - var frameworksNode = root.SelectNodes("/Project/PropertyGroup/TargetFrameworks").NodeList().Concat( - root.SelectNodes("/Project/PropertyGroup/TargetFramework").NodeList()).Select(node => node.InnerText); - var relativeCsIncludes2 = root.SelectNodes("/Project/ItemGroup/Compile/@Include", mgr). NodeList(). diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs index 4aad28068b0..299770a47e1 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs @@ -24,7 +24,7 @@ namespace Semmle.BuildAnalyser /// sealed class FileRenamer : IDisposable { - string[] files; + readonly string[] files; const string suffix = ".codeqlhidden"; public FileRenamer(IEnumerable oldFiles) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs index dade3909635..ddb744ab4f7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs @@ -114,16 +114,15 @@ namespace Semmle.BuildAnalyser try { - using (var p = Process.Start(pi)) - { - string output = p.StandardOutput.ReadToEnd(); - string error = p.StandardError.ReadToEnd(); + using var p = Process.Start(pi); - p.WaitForExit(); - if (p.ExitCode != 0) - { - pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error); - } + string output = p.StandardOutput.ReadToEnd(); + string error = p.StandardError.ReadToEnd(); + + p.WaitForExit(); + if (p.ExitCode != 0) + { + pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error); } } catch (Exception ex) @@ -136,6 +135,10 @@ namespace Semmle.BuildAnalyser readonly string nugetExe; } + /// + /// A temporary directory that is created within the system temp directory. + /// When this object is disposed, the directory is deleted. + /// sealed class TemporaryDirectory : IDisposable { public DirectoryInfo DirInfo { get; } @@ -156,7 +159,7 @@ namespace Semmle.BuildAnalyser { var bytes = Encoding.Unicode.GetBytes(srcDir); - var sha1 = new SHA1CryptoServiceProvider(); + using var sha1 = new SHA1CryptoServiceProvider(); var sha = sha1.ComputeHash(bytes); var sb = new StringBuilder(); foreach (var b in sha.Take(8)) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs index 75c2bf31e6d..2dc6e2cd287 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs @@ -85,7 +85,7 @@ namespace Semmle.Extraction.CSharp.Standalone static int Main(string[] args) { var options = Options.Create(args); - options.CIL = true; + // options.CIL = true; // To do: Enable this var output = new ConsoleLogger(options.Verbosity); var a = new Analysis(output); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index c2cb6a367eb..6050ad910a5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -214,7 +214,6 @@ namespace Semmle.Extraction.CSharp static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) { bool prefixAssembly = true; - if (cx.Extractor.Standalone) prefixAssembly = false; if (named.ContainingAssembly is null) prefixAssembly = false; if (named.IsTupleType) diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll index c0d75bfd9fe..d1e1017e0d1 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll @@ -388,7 +388,12 @@ library class PropertyAccessExpr extends Expr, @property_access_expr { /** Gets the target of this property access. */ Property getProperty() { expr_access(this, result) } - override string toString() { result = "access to property " + this.getProperty().getName() } + override string toString() { + result = "access to property " + this.getProperty().getName() + or + not exists(this.getProperty()) and + result = "access to property (unknown)" + } } /** diff --git a/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected b/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected index 06473196df9..a9eb533c152 100644 --- a/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected +++ b/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected @@ -7,9 +7,14 @@ | ControlFlow.cs:10:9:10:43 | Call (unknown target) | ControlFlow.cs:12:9:12:87 | ...; | | ControlFlow.cs:10:9:10:43 | call to method | ControlFlow.cs:12:9:12:87 | ...; | | ControlFlow.cs:10:9:10:44 | ...; | ControlFlow.cs:10:9:10:13 | Expression | -| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Expression | -| ControlFlow.cs:10:22:10:24 | Expression | ControlFlow.cs:10:22:10:26 | Expression | -| ControlFlow.cs:10:22:10:26 | Expression | ControlFlow.cs:10:29:10:42 | "This is true" | +| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Call (unknown target) | +| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | access to property (unknown) | +| ControlFlow.cs:10:22:10:24 | Call (unknown target) | ControlFlow.cs:10:22:10:26 | Call (unknown target) | +| ControlFlow.cs:10:22:10:24 | Call (unknown target) | ControlFlow.cs:10:22:10:26 | access to property (unknown) | +| ControlFlow.cs:10:22:10:24 | access to property (unknown) | ControlFlow.cs:10:22:10:26 | Call (unknown target) | +| ControlFlow.cs:10:22:10:24 | access to property (unknown) | ControlFlow.cs:10:22:10:26 | access to property (unknown) | +| ControlFlow.cs:10:22:10:26 | Call (unknown target) | ControlFlow.cs:10:29:10:42 | "This is true" | +| ControlFlow.cs:10:22:10:26 | access to property (unknown) | ControlFlow.cs:10:29:10:42 | "This is true" | | ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | Call (unknown target) | | ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | call to method | | ControlFlow.cs:12:9:12:86 | Call (unknown target) | ControlFlow.cs:12:37:12:47 | Expression | @@ -20,5 +25,7 @@ | ControlFlow.cs:12:51:12:62 | access to field Empty | ControlFlow.cs:12:37:12:62 | ... = ... | | ControlFlow.cs:12:65:12:75 | Expression | ControlFlow.cs:12:79:12:79 | access to local variable v | | ControlFlow.cs:12:65:12:84 | ... = ... | ControlFlow.cs:12:35:12:86 | { ..., ... } | -| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | Expression | -| ControlFlow.cs:12:79:12:84 | Expression | ControlFlow.cs:12:65:12:84 | ... = ... | +| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | Call (unknown target) | +| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | access to property (unknown) | +| ControlFlow.cs:12:79:12:84 | Call (unknown target) | ControlFlow.cs:12:65:12:84 | ... = ... | +| ControlFlow.cs:12:79:12:84 | access to property (unknown) | ControlFlow.cs:12:65:12:84 | ... = ... | diff --git a/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected b/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected index 05ae24318c3..d57c3c86bbd 100644 --- a/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected +++ b/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected @@ -2,5 +2,5 @@ | errors.cs:43:21:43:28 | errors.cs:43:21:43:28 | object creation of type C1 | C1 | | errors.cs:44:13:44:19 | errors.cs:44:13:44:19 | call to method m1 | m1 | | errors.cs:45:13:45:19 | errors.cs:45:13:45:19 | call to method m2 | m2 | -| errors.cs:46:13:46:38 | errors.cs:46:13:46:38 | call to method | none | +| errors.cs:46:13:46:38 | errors.cs:46:13:46:38 | call to method WriteLine | WriteLine | | errors.cs:53:17:53:25 | errors.cs:53:17:53:25 | object creation of type C2 | none | diff --git a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected index 47045b907f6..2c8616d347a 100644 --- a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected +++ b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected @@ -1,2 +1,3 @@ -| regressions.cs:16:13:16:37 | case ...: | regressions.cs:16:18:16:36 | Expression | -| regressions.cs:18:13:18:37 | case ...: | regressions.cs:18:18:18:36 | Expression | +| regressions.cs:16:13:16:37 | case ...: | regressions.cs:16:18:16:36 | access to property (unknown) | +| regressions.cs:18:13:18:37 | case ...: | regressions.cs:18:18:18:36 | access to property (unknown) | +| regressions.cs:20:13:20:23 | case ...: | regressions.cs:20:18:20:22 | Int32 x | diff --git a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql index 7ee7754e91e..6c5d54518fe 100644 --- a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql +++ b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql @@ -1,7 +1,5 @@ import csharp from Case c, Expr e -where - e = c.getPattern().stripCasts() and - (e instanceof @unknown_expr or e instanceof ConstantPatternExpr) +where e = c.getPattern().stripCasts() select c, e From d3e1a258fad225a70eafd9a00f743763cd114d04 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Mar 2020 17:48:51 +0100 Subject: [PATCH 154/459] autoformat --- .../javascript/dataflow/TaintTracking.qll | 66 ++++++++++--------- .../security/dataflow/DomBasedXss.qll | 4 +- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 31b9bc7947d..85553d85918 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -636,7 +636,7 @@ module TaintTracking { } /** - * Holds if `params` is a construction of a `URLSearchParams` that parses + * Holds if `params` is a construction of a `URLSearchParams` that parses * the parameters in `input`. */ predicate isUrlSearchParams(DataFlow::SourceNode params, DataFlow::Node input) { @@ -650,45 +650,47 @@ module TaintTracking { /** * A pseudo-property a `URL` that stores a value that can be obtained - * with a `get` or `getAll` call to the `searchParams` property. + * with a `get` or `getAll` call to the `searchParams` property. */ - private string hiddenUrlPseudoProperty() { - result = "$hiddenSearchPararms" - } + private string hiddenUrlPseudoProperty() { result = "$hiddenSearchPararms" } /** * A pseudo-property on a `URLSearchParams` that can be obtained - * with a `get` or `getAll` call. - */ - private string getableUrlPseudoProperty() { - result = "$gettableSearchPararms" - } + * with a `get` or `getAll` call. + */ + private string getableUrlPseudoProperty() { result = "$gettableSearchPararms" } /** * A taint propagating data flow edge arising from URL parameter parsing. */ private class UrlSearchParamsTaintStep extends DataFlow::AdditionalFlowStep, DataFlow::ValueNode { /** - * Holds if `succ` is a `URLSearchParams` providing access to the - * parameters encoded in `pred`. - */ + * Holds if `succ` is a `URLSearchParams` providing access to the + * parameters encoded in `pred`. + */ override predicate step(DataFlow::Node pred, DataFlow::Node succ) { isUrlSearchParams(succ, pred) and succ = this } /** * Holds if `pred` should be stored in the object `succ` under the property `prop`. - * - * This step is used to model 3 facts: + * + * This step is used to model 3 facts: * 1) A `URL` constructed using `url = new URL(input)` transfers taint from `input` to `url.searchParams`, `url.hash`, and `url.search`. * 2) Accessing the `searchParams` on a `URL` results in a `URLSearchParams` object (See the loadStoreStep method on this class and hiddenUrlPseudoProperty()) - * 3) A `URLSearchParams` object (either `url.searchParams` or `new URLSearchParams(input)`) has a tainted value, + * 3) A `URLSearchParams` object (either `url.searchParams` or `new URLSearchParams(input)`) has a tainted value, * which can be accessed using a `get` or `getAll` call. (See getableUrlPseudoProperty()) */ override predicate storeStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { - succ = this and ( - (prop = "searchParams" or prop = "hash" or prop = "search" or prop = hiddenUrlPseudoProperty()) and - exists(DataFlow::NewNode newUrl | succ = newUrl | + succ = this and + ( + ( + prop = "searchParams" or + prop = "hash" or + prop = "search" or + prop = hiddenUrlPseudoProperty() + ) and + exists(DataFlow::NewNode newUrl | succ = newUrl | newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and pred = newUrl.getArgument(0) ) @@ -700,26 +702,28 @@ module TaintTracking { /** * Holds if the property `loadStep` should be copied from the object `pred` to the property `storeStep` of object `succ`. - * - * This step is used to copy the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. - * For an expression `url.searchParams`, the property `hiddenUrlPseudoProperty()` from the `url` object is stored in the property `getableUrlPseudoProperty()` on `url.searchParams`. + * + * This step is used to copy the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. + * For an expression `url.searchParams`, the property `hiddenUrlPseudoProperty()` from the `url` object is stored in the property `getableUrlPseudoProperty()` on `url.searchParams`. */ - override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { + override predicate loadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { succ = this and loadProp = hiddenUrlPseudoProperty() and storeProp = getableUrlPseudoProperty() and - exists(DataFlow::PropRead read | read = succ | + exists(DataFlow::PropRead read | read = succ | read.getPropertyName() = "searchParams" and read.getBase() = pred ) } - /** - * Holds if the property `prop` of the object `pred` should be loaded into `succ`. - * - * This step is used to load the value stored in the pseudo-property `getableUrlPseudoProperty()`. - */ - override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + /** + * Holds if the property `prop` of the object `pred` should be loaded into `succ`. + * + * This step is used to load the value stored in the pseudo-property `getableUrlPseudoProperty()`. + */ + override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { succ = this and prop = getableUrlPseudoProperty() and // this is a call to `get` or `getAll` on a `URLSearchParams` object @@ -728,7 +732,7 @@ module TaintTracking { call.getReceiver() = pred and m.matches("get%") ) - } + } } /** diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll index e190ccf735c..a1b2a4bf6d9 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll @@ -49,7 +49,5 @@ module DomBasedXss { } } - private string urlSuffixPseudoProperty() { - result = "$UrlSuffix$" - } + private string urlSuffixPseudoProperty() { result = "$UrlSuffix$" } } From 58af63d8ccca990d7afbb9e911d0445a5192b872 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 27 Mar 2020 10:02:24 +0100 Subject: [PATCH 155/459] add test case for XSS on url suffix --- .../ql/test/query-tests/Security/CWE-079/Xss.expected | 9 +++++++++ .../Security/CWE-079/XssWithAdditionalSources.expected | 8 ++++++++ javascript/ql/test/query-tests/Security/CWE-079/tst.js | 9 +++++++++ 3 files changed, 26 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected index 5f8bf041b2b..7008a475825 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected @@ -337,6 +337,10 @@ nodes | tst.js:330:18:330:34 | document.location | | tst.js:336:18:336:35 | params.get('name') | | tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | +| tst.js:347:20:347:36 | document.location | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:20:13:20:45 | target | | typeahead.js:20:22:20:38 | document.location | | typeahead.js:20:22:20:38 | document.location | @@ -650,6 +654,10 @@ edges | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target | | typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search | | typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search | @@ -750,6 +758,7 @@ edges | tst.js:314:20:314:20 | e | tst.js:311:10:311:17 | location | tst.js:314:20:314:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:311:10:311:17 | location | user-provided value | | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | Cross-site scripting vulnerability due to $@. | tst.js:319:35:319:42 | location | user-provided value | | tst.js:336:18:336:35 | params.get('name') | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | Cross-site scripting vulnerability due to $@. | tst.js:330:18:330:34 | document.location | user-provided value | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | Cross-site scripting vulnerability due to $@. | tst.js:347:20:347:36 | document.location | user-provided value | | typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:38 | document.location | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:38 | document.location | user-provided value | | v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value | | winjs.js:3:43:3:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:3:43:3:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected index c7fdb071a2b..0f4f4e4d2ea 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected @@ -337,6 +337,10 @@ nodes | tst.js:330:18:330:34 | document.location | | tst.js:336:18:336:35 | params.get('name') | | tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | +| tst.js:347:20:347:36 | document.location | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:9:28:9:30 | loc | | typeahead.js:9:28:9:30 | loc | | typeahead.js:10:16:10:18 | loc | @@ -654,6 +658,10 @@ edges | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/tst.js b/javascript/ql/test/query-tests/Security/CWE-079/tst.js index a5fefc233eb..99a50e9ab9c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/tst.js @@ -339,4 +339,13 @@ function URLPseudoProperties() { let myUrl = getTaintedUrl(); $('name').html(myUrl.get('name')); +} + + +function hash() { + function getUrl() { + return new URL(document.location); + } + $(getUrl().hash.substring(1)); // NOT OK + } \ No newline at end of file From f9442211bf9d85c782f23afee1625cc43d712969 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 11:31:25 +0000 Subject: [PATCH 156/459] unique aggregate in handbook and reference --- docs/language/ql-handbook/expressions.rst | 15 +++++++++++++++ docs/language/ql-spec/language.rst | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index 27e8543e4f5..e1e4a099dad 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -279,6 +279,21 @@ The following aggregates are available in QL: evaluates to the empty set (instead of defaulting to ``0`` or the empty string). This is useful if you're only interested in results where the aggregation body is non-trivial. +.. index: unique + +- ``unique``: The value of this aggregate depends on how many different values ```` can have, + within the context of a fixed set of assignments to outside variables. + If the value is uniquely determined, then the aggregate gives that value. Otherwise, it has no value. + + For example, the following aggregation yields the positive integers ``1``, ``2``, ``3``, ``4``, ``5``. + For negative integers ``x``, the expressions ``x`` and ``x.abs()`` have different values and hence the + value for ``y`` in the aggregate expression is not uniquely determined. :: + + from int x + where x in [-5 .. 5] and x != 0 + select unique(int y | y = x and y = x.abs() | y) + + The ``unique`` aggregate is supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise. Evaluation of aggregates ======================== diff --git a/docs/language/ql-spec/language.rst b/docs/language/ql-spec/language.rst index eb434ef071f..796fe17dfc2 100644 --- a/docs/language/ql-spec/language.rst +++ b/docs/language/ql-spec/language.rst @@ -1960,7 +1960,8 @@ The complete grammar for QL is as follows: aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" - + | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" + aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" aggorderbys ::= aggorderby ("," aggorderby)* From 5ba5791ec6511b31591b11313da570bcb86a57c6 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 27 Mar 2020 13:37:17 +0100 Subject: [PATCH 157/459] C++: Only allow flow through non-conflated chi instructions --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 3 +-- .../dataflow/fields/ir-flow.expected | 15 --------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 123841c47cf..367d49bb2a7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -219,7 +219,7 @@ abstract class PostUpdateNode extends InstructionNode { abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { final Instruction getInstructionOrChi() { exists(ChiInstruction chi | - // TODO: This should be a non-conflated ChiInstruction once #3123 is merged + not chi.isResultConflated() and chi.getPartial() = getInstruction() and result = chi ) @@ -356,7 +356,6 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) or exists(LoadInstruction load | - // TODO: These can probably be getSourceValue() after #3112 is merged load.getSourceValueOperand().getAnyDef() = nodeFrom.(PartialDefinitionNode).getInstructionOrChi() and nodeTo.asInstruction() = load.getSourceAddress().(FieldAddressInstruction).getObjectAddress() diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index f455b37bf49..3c7bbe96a7d 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -1,10 +1,4 @@ edges -| A.cpp:126:5:126:5 | IndirectMayWriteSideEffect [c] : void | A.cpp:131:8:131:8 | BufferMayWriteSideEffect [c] : void | -| A.cpp:126:12:126:18 | new : void | A.cpp:126:5:126:5 | IndirectMayWriteSideEffect [c] : void | -| A.cpp:131:8:131:8 | BufferMayWriteSideEffect [c] : void | A.cpp:132:10:132:10 | b [c] : void | -| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c | -| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c : void | -| A.cpp:132:13:132:13 | c : void | A.cpp:132:10:132:13 | (void *)... | | aliasing.cpp:9:3:9:22 | Store : void | aliasing.cpp:9:3:9:22 | Store [m1] : void | | aliasing.cpp:9:3:9:22 | Store [m1] : void | aliasing.cpp:25:17:25:19 | BufferMayWriteSideEffect [m1] : void | | aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:9:3:9:22 | Store : void | @@ -58,13 +52,6 @@ edges | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | | struct_init.c:31:14:31:21 | nestedAB [a] : void | struct_init.c:31:23:31:23 | a | nodes -| A.cpp:126:5:126:5 | IndirectMayWriteSideEffect [c] : void | semmle.label | IndirectMayWriteSideEffect [c] : void | -| A.cpp:126:12:126:18 | new : void | semmle.label | new : void | -| A.cpp:131:8:131:8 | BufferMayWriteSideEffect [c] : void | semmle.label | BufferMayWriteSideEffect [c] : void | -| A.cpp:132:10:132:10 | b [c] : void | semmle.label | b [c] : void | -| A.cpp:132:10:132:13 | (void *)... | semmle.label | (void *)... | -| A.cpp:132:13:132:13 | c | semmle.label | c | -| A.cpp:132:13:132:13 | c : void | semmle.label | c : void | | aliasing.cpp:9:3:9:22 | Store : void | semmle.label | Store : void | | aliasing.cpp:9:3:9:22 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:9:11:9:20 | call to user_input : void | semmle.label | call to user_input : void | @@ -113,8 +100,6 @@ nodes | struct_init.c:31:14:31:21 | nestedAB [a] : void | semmle.label | nestedAB [a] : void | | struct_init.c:31:23:31:23 | a | semmle.label | a | #select -| A.cpp:132:10:132:13 | (void *)... | A.cpp:126:12:126:18 | new : void | A.cpp:132:10:132:13 | (void *)... | (void *)... flows from $@ | A.cpp:126:12:126:18 | new : void | new : void | -| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new : void | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new : void | new : void | | aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input : void | call to user_input : void | | aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input : void | call to user_input : void | | aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void | From deb657acdb099a3ee349535e25b8781b90234b61 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 26 Mar 2020 10:55:36 +0000 Subject: [PATCH 158/459] docs: tidy up 'codeql for x' pages Manually construct tocs including intro text. Fix a few intros and titles. --- docs/language/learn-ql/cpp/dataflow.rst | 2 +- docs/language/learn-ql/cpp/ql-for-cpp.rst | 30 ++++++++++++++----- .../csharp/introduce-libraries-csharp.rst | 6 ++-- .../learn-ql/csharp/ql-for-csharp.rst | 18 ++++------- docs/language/learn-ql/go/ql-for-go.rst | 5 ++-- docs/language/learn-ql/java/ql-for-java.rst | 26 ++++++++-------- .../javascript/introduce-libraries-js.rst | 6 ++-- .../javascript/introduce-libraries-ts.rst | 6 ++-- .../learn-ql/javascript/ql-for-javascript.rst | 17 +++++------ .../learn-ql/javascript/type-tracking.rst | 3 +- .../learn-ql/python/ql-for-python.rst | 25 ++++++++++++++-- 11 files changed, 82 insertions(+), 62 deletions(-) diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index c3ba52cd62f..e926eeb8e60 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -1,7 +1,7 @@ Analyzing data flow in C and C++ ================================ -You can use data-flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase. +You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase. About data flow --------------- diff --git a/docs/language/learn-ql/cpp/ql-for-cpp.rst b/docs/language/learn-ql/cpp/ql-for-cpp.rst index 3a82d43b662..8961c3ef80a 100644 --- a/docs/language/learn-ql/cpp/ql-for-cpp.rst +++ b/docs/language/learn-ql/cpp/ql-for-cpp.rst @@ -1,11 +1,10 @@ -CodeQL for C/C++ -================ +CodeQL for C and C++ +==================== - -Learn how to write queries using the standard CodeQL libraries for C and C++. +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C and C++ codebases. .. toctree:: - :maxdepth: 1 + :hidden: introduce-libraries-cpp function-classes @@ -18,10 +17,25 @@ Learn how to write queries using the standard CodeQL libraries for C and C++. range-analysis value-numbering-hash-cons -Other resources ---------------- -.. TODO: Rename the cookbooks: C/C++ cookbook, or C/C++ CodeQL cookbook, or CodeQL cookbook for C/C++, or...? +- `Basic C/C++ query `__: Learn to write and run a simple CodeQL query using LGTM. + +- :doc:`CodeQL library for C and C++ `: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++. + +- :doc:`Functions in C and C++ `: You can use CodeQL to explore functions in C and C++ code. + +- :doc:`Expressions, types, and statements in C and C++ `: You can use CodeQL to explore expressions, types, and statements in C and C++ code to find, for example, incorrect assignments. + +- :doc:`Conversions and classes in C and C++ `: You can use the standard CodeQL libraries for C and C++ to detect when the type of an expression is changed. + +- :doc:`Analyzing data flow in C and C++ `: You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase. + +- :doc:`Refining a query to account for edge cases `: You can improve the results generated by a CodeQL query by adding conditions to remove false positive results caused by common edge cases. + +- :doc:`Detecting a potential buffer overflow `: You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. + +Further reading +--------------- - For examples of how to query common C/C++ elements, see the `C/C++ cookbook `__. - For the queries used in LGTM, display a `C/C++ query `__ and click **Open in query console** to see the code used to find alerts. diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index 501c8591f2d..1751657b99b 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1,7 +1,7 @@ -CodeQL libraries for C# -======================= +CodeQL library for C# +===================== -When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL libraries for C#. +When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL library for C#. About the CodeQL libraries for C# --------------------------------- diff --git a/docs/language/learn-ql/csharp/ql-for-csharp.rst b/docs/language/learn-ql/csharp/ql-for-csharp.rst index 02dddda60ec..6eb3567e808 100644 --- a/docs/language/learn-ql/csharp/ql-for-csharp.rst +++ b/docs/language/learn-ql/csharp/ql-for-csharp.rst @@ -1,29 +1,21 @@ CodeQL for C# ============= -You can use CodeQL to explore C# programs and quickly find variants of security vulnerabilities and bugs. +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C# codebases. .. toctree:: - :glob: :hidden: introduce-libraries-csharp dataflow -These topics provide an overview of the CodeQL libraries for C# and show examples of how to use them. +- `Basic C# query `__: Learn to write and run a simple CodeQL query using LGTM. -- `Basic C# query `__ describes how to write and run queries using LGTM. +- :doc:`CodeQL library for C# `: When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL library for C#. -- :doc:`Introducing the CodeQL libraries for C# ` introduces the standard libraries used to write queries for C# code. +- :doc:`Analyzing data flow in C# `: You can use CodeQL to track the flow of data through a C# program to its use. -.. raw:: html - - - -- :doc:`Analyzing data flow in C# ` demonstrates how to write queries using the standard data flow and taint tracking libraries for C#. - - -Other resources +Further reading --------------- - For examples of how to query common C# elements, see the `C# cookbook `__. diff --git a/docs/language/learn-ql/go/ql-for-go.rst b/docs/language/learn-ql/go/ql-for-go.rst index baa390dc7c6..2528cbe478c 100644 --- a/docs/language/learn-ql/go/ql-for-go.rst +++ b/docs/language/learn-ql/go/ql-for-go.rst @@ -1,10 +1,9 @@ CodeQL for Go ============= -This page provides an overview of the CodeQL for Go documentation that is currently available. - -- `Basic Go query `__ describes how to write and run queries using LGTM. +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Go codebases. +- `Basic Go query `__: Learn to write and run a simple CodeQL query using LGTM. Other resources --------------- diff --git a/docs/language/learn-ql/java/ql-for-java.rst b/docs/language/learn-ql/java/ql-for-java.rst index 9ff0b24438a..fccaecca247 100644 --- a/docs/language/learn-ql/java/ql-for-java.rst +++ b/docs/language/learn-ql/java/ql-for-java.rst @@ -1,10 +1,9 @@ CodeQL for Java =============== -You can use CodeQL to explore Java programs and quickly find variants of security vulnerabilities and bugs. +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Java codebases. .. toctree:: - :glob: :hidden: introduce-libraries-java @@ -17,29 +16,28 @@ You can use CodeQL to explore Java programs and quickly find variants of securit source-locations ast-class-reference -These topics provide an overview of the CodeQL libraries for Java and show examples of how to use them. +- `Basic Java query `__: Learn to write and run a simple CodeQL query using LGTM. -- `Basic Java query `__ describes how to write and run queries using LGTM. +- :doc:`CodeQL library for Java `: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++. -- :doc:`CodeQL libraries for Java ` introduces the standard libraries used to write queries for Java code. +- :doc:`Analyzing data flow in Java `: You can use CodeQL to track the flow of data through a Java program to its use. -- :doc:`Analyzing data flow in Java ` demonstrates how to write queries using the standard data flow and taint tracking libraries for Java. +- :doc:`Java types `: You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues. -- :doc:`Types in Java ` introduces the classes for representing a program's class hierarchy by means of examples. +- :doc:`Overflow-prone comparisons in Java `: You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow. -- :doc:`Expressions and statements in Java ` introduces the classes for representing a program's syntactic structure by means of examples. +- :doc:`Navigating the call graph `: CodeQL has classes for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used. -- :doc:`Navigating the call graph ` is a worked example of how to write a query that navigates a program's call graph to find unused methods. +- :doc:`Annotations in Java `: CodeQL databases of Java projects contain information about all annotations attached to program elements. -- :doc:`Annotations in Java ` introduces the classes for representing annotations by means of examples. +- :doc:`Javadoc `: You can use CodeQL to find errors in Javadoc comments in Java code. -- :doc:`Javadoc ` introduces the classes for representing Javadoc comments by means of examples. +- :doc:`Working with source locations `: You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. -- :doc:`Working with source locations ` is a worked example of how to write a query that uses the location information provided in the database for finding likely bugs. +- :doc:`lasses for working with Java code `: CodeQL has a large selection of classes for working with Java statements and expressions. -- :doc:`AST class reference ` gives an overview of all AST classes in the standard CodeQL library for Java. -Other resources +Further reading --------------- - For examples of how to query common Java elements, see the `Java cookbook `__. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 0e7b6a94ab6..0b161d32ec6 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1,7 +1,7 @@ -CodeQL libraries for JavaScript -=============================== +CodeQL library for JavaScript +============================= -You can use the extensive libraries described in this article to analyze databases generated from JavaScript codebases. Using these libraries makes it easier for you to write queries. +When you're analyzing a JavaScript program, you can make use of the large collection of classes in the CodeQL library for JavaScript. Overview -------- diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index 765fdf2d694..d6cca17749d 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -1,7 +1,7 @@ -CodeQL libraries for TypeScript -=============================== +CodeQL library for TypeScript +============================= -You can use libraries to analyze databases generated from TypeScript codebases. Using these libraries makes it easier for you to write queries. +When you're analyzing a TypeScript program, you can make use of the large collection of classes in the CodeQL library for TypeScript. Overview -------- diff --git a/docs/language/learn-ql/javascript/ql-for-javascript.rst b/docs/language/learn-ql/javascript/ql-for-javascript.rst index 14c6439e105..5e10e9f979d 100644 --- a/docs/language/learn-ql/javascript/ql-for-javascript.rst +++ b/docs/language/learn-ql/javascript/ql-for-javascript.rst @@ -4,7 +4,6 @@ CodeQL for JavaScript Experiment and learn how to write effective and efficient queries for CodeQL databases generated from JavaScript codebases. .. toctree:: - :glob: :hidden: introduce-libraries-js @@ -15,21 +14,21 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat ast-class-reference dataflow-cheat-sheet -These documents provide an overview of the CodeQL libraries for JavaScript and TypeScript and show examples of how to use them. +- `Basic JavaScript query `__: Learn to write and run a simple CodeQL query using LGTM. -- `Basic JavaScript query `__ describes how to write and run queries using LGTM. +- :doc:`CodeQL library for JavaScript `: When you're analyzing a JavaScript program, you can make use of the large collection of classes in the CodeQL library for JavaScript. -- :doc:`CodeQL libraries for JavaScript ` introduces the standard libraries used to write queries for JavaScript code. There is an extensive CodeQL library for analyzing JavaScript code. This tutorial briefly summarizes the most important classes and predicates provided by this library. +- :doc:`CodeQL library for TypeScript `: When you're analyzing a TypeScript program, you can make use of the large collection of classes in the CodeQL library for TypeScript. -- :doc:`CodeQL libraries for TypeScript ` introduces the standard libraries used to write queries for TypeScript code. +- :doc:`Analyzing data flow in JavaScript and TypeScript `: This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. -- :doc:`Analyzing data flow in JavaScript and TypeScript ` demonstrates how to write queries using the standard data flow and taint tracking libraries for JavaScript/TypeScript. +- :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. -- :doc:`Using flow labels for precise data flow analysis ` shows a more advanced example of data flow analysis using flow labels. +- :doc:`Using type tracking for API modeling `: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. -- :doc:`Abstract syntax tree classes for JavaScript and TypeScript ` gives an overview of all AST classes in the standard CodeQL library for JavaScript. +- :doc:`Abstract syntax tree classes for JavaScript and TypeScript `: CodeQL has a large selection of classes for working with JavaScript and TypeScript statements and expressions. -- :doc:`Data flow cheat sheet for JavaScript ` lists parts of the CodeQL libraries that are commonly used for variant analysis and in data flow queries. +- :doc:`Data flow cheat sheet for JavaScript `: This article describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries. Further reading --------------- diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index da8378a8e71..61b172ef665 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -1,8 +1,7 @@ Using type tracking for API modeling ==================================== -You can track data through an API by creating a model -using the CodeQL type-tracking library for JavaScript. +You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. Overview -------- diff --git a/docs/language/learn-ql/python/ql-for-python.rst b/docs/language/learn-ql/python/ql-for-python.rst index b4f47e8a70c..d43dc95dbd5 100644 --- a/docs/language/learn-ql/python/ql-for-python.rst +++ b/docs/language/learn-ql/python/ql-for-python.rst @@ -1,11 +1,10 @@ CodeQL for Python ================= -Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Python code bases. +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Python codebases. .. toctree:: - :glob: - :maxdepth: 2 + :hidden: introduce-libraries-python functions @@ -14,3 +13,23 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat control-flow taint-tracking +- `Basic Python query `__ : Learn to write and run a simple CodeQL query using LGTM. + +- :doc:`CodeQL library for Python `: When you need to analyze a Python program, you can make use of the large collection of classes in the CodeQL library for Python. + +- :doc:`Functions in Python `: You can use syntactic classes from the standard CodeQL library to find Python functions and identify calls to them. + +- :doc:`Expressions and statements in Python `: You can use syntactic classes from the CodeQL library to explore how Python expressions and statements are used in a code base. + +- :doc:`Analyzing control flow in Python `: You can write CodeQL queries to explore the control-flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. + +- :doc:`Pointer analysis and type inference in Python `: At runtime, each Python expression has a value with an associated type. You can learn how an expression behaves at runtime by using type-inference classes from the standard CodeQL library. + +- :doc:`Analyzing data flow and tracking tainted data in Python `: You can use CodeQL to track the flow of data through a Python program. Tracking user-controlled, or tainted, data is a key technique for security researchers. + +Further reading +--------------- + +- For examples of how to query common Python elements, see the `JavaScript cookbook `__. +- For the queries used in LGTM, display a `Python query `__ and click **Open in query console** to see the code used to find alerts. +- For more information about the library for JavaScript see the `CodeQL library for Python `__. \ No newline at end of file From 76f344638e0edbc96c412d899cecf7d74c636eb5 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 27 Mar 2020 07:38:05 +0000 Subject: [PATCH 159/459] docs: 'What's new' -> 'Further reading' --- docs/language/learn-ql/beginner/ql-tutorials.rst | 6 ++++++ .../learn-ql/cobol/introduce-libraries-cobol.rst | 4 ++-- docs/language/learn-ql/cpp/conversions-classes.rst | 4 ++-- docs/language/learn-ql/cpp/dataflow.rst | 4 ++-- docs/language/learn-ql/cpp/expressions-types.rst | 4 ++-- docs/language/learn-ql/cpp/function-classes.rst | 4 ++-- .../learn-ql/cpp/introduce-libraries-cpp.rst | 4 ++-- .../learn-ql/cpp/private-field-initialization.rst | 4 ++-- .../language/learn-ql/cpp/zero-space-terminator.rst | 11 +++-------- docs/language/learn-ql/csharp/dataflow.rst | 1 - docs/language/learn-ql/java/dataflow.rst | 4 ++-- docs/language/learn-ql/javascript/dataflow.rst | 4 ++-- docs/language/learn-ql/javascript/type-tracking.rst | 4 ++-- .../learn-ql/writing-queries/query-metadata.rst | 2 +- .../learn-ql/writing-queries/writing-queries.rst | 13 +++++++++++-- 15 files changed, 41 insertions(+), 32 deletions(-) diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index 53f8ab7def2..6585653644d 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -6,8 +6,14 @@ Solve puzzles to learn the basics of QL before you analyze code with CodeQL. The Before starting these tutorials, you can read the :doc:`Introduction to QL <../introduction-to-ql>` for a description of the language and some simple examples. .. toctree:: + :hidden: find-the-thief catch-the-fire-starter crown-the-rightful-heir cross-the-river + +- :doc:`Find the thief `:Take on the role of a detective to find the thief in this fictional village. You will learn how to use logical connectives, quantifiers, and aggregates in QL along the way. +- :doc:`Catch the fire starter `: Learn about QL predicates and classes to solve your second mystery as a QL detective. +- :doc:`Crown the rightful heir `: This is a QL detective puzzle that shows you how to use recursion in QL to write more complex queries. +- :doc:`Cross the river `: Use common QL features to write a query that finds a solution to the "River crossing" logic puzzle. diff --git a/docs/language/learn-ql/cobol/introduce-libraries-cobol.rst b/docs/language/learn-ql/cobol/introduce-libraries-cobol.rst index 34cfbba057a..e34c6c13ff5 100644 --- a/docs/language/learn-ql/cobol/introduce-libraries-cobol.rst +++ b/docs/language/learn-ql/cobol/introduce-libraries-cobol.rst @@ -145,7 +145,7 @@ SQL Calls to the SQL system through ``EXEC SQL`` are represented by the class `SqlStmt `__ and its subclasses. -What next? ----------- +Further reading +--------------- - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index fc087ae5c31..054d082f9ef 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -220,8 +220,8 @@ That completes the query. There is a similar built-in `query `__ on LGTM.com that finds classes in a C/C++ project with virtual functions but no virtual destructor. You can take a look at the code for this query by clicking **Open in query console** at the top of that page. -What next? ----------- +Further reading +--------------- - Explore other ways of querying classes using examples from the `C/C++ cookbook `__. - Take a look at the :doc:`Analyzing data flow in C and C++ ` tutorial. diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index e926eeb8e60..b4bffe595ea 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -295,8 +295,8 @@ Exercise 3: Write a class that represents flow sources from ``getenv``. (`Answer Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flows from ``getenv`` to ``gethostbyname``. (`Answer <#exercise-4>`__) -What next? ----------- +Further reading +--------------- - Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases ` and :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/cpp/expressions-types.rst b/docs/language/learn-ql/cpp/expressions-types.rst index c88b5fc24db..5894bccb113 100644 --- a/docs/language/learn-ql/cpp/expressions-types.rst +++ b/docs/language/learn-ql/cpp/expressions-types.rst @@ -129,8 +129,8 @@ We can find assignments inside the loop body using similar code with the predica Note that we replaced ``e.getEnclosingStmt()`` with ``e.getEnclosingStmt().getParentStmt*()``, to find an assignment expression that is deeply nested inside the loop body. The transitive closure modifier ``*`` here indicates that ``Stmt.getParentStmt()`` may be followed zero or more times, rather than just once, giving us the statement, its parent statement, its parent's parent statement etc. -What next? ----------- +Further reading +--------------- - Explore other ways of finding types and statements using examples from the C/C++ cookbook for `types `__ and `statements `__. - Take a look at the :doc:`Conversions and classes in C and C++ ` and :doc:`Analyzing data flow in C and C++ ` tutorials. diff --git a/docs/language/learn-ql/cpp/function-classes.rst b/docs/language/learn-ql/cpp/function-classes.rst index 3f3350d8bb0..a6c15ebfa11 100644 --- a/docs/language/learn-ql/cpp/function-classes.rst +++ b/docs/language/learn-ql/cpp/function-classes.rst @@ -89,8 +89,8 @@ Note that we could have used ``Declaration.getName()``, but ``Declaration.getQua The LGTM version of this query is considerably more complicated, but if you look carefully you will find that its structure is the same. See `Non-constant format string `__ and click **Open in query console** at the top of the page. -What next? ----------- +Further reading +--------------- - Explore other ways of finding functions using examples from the `C/C++ cookbook `__. - Take a look at some other tutorials: :doc:`Expressions, types and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 63cd93a0a82..60e82d98f0a 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -520,8 +520,8 @@ This table lists `Preprocessor `, :doc:`Expressions, types, and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/cpp/private-field-initialization.rst b/docs/language/learn-ql/cpp/private-field-initialization.rst index 852f982daa2..4a1c858fd85 100644 --- a/docs/language/learn-ql/cpp/private-field-initialization.rst +++ b/docs/language/learn-ql/cpp/private-field-initialization.rst @@ -146,8 +146,8 @@ Finally we can simplify the query by using the transitive closure operator. In t ➤ `See this in the query console `__ -What next? ----------- +Further reading +--------------- - Take a look at another example: :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index c6e2a557aaa..8c01a2e3cd9 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -1,12 +1,7 @@ Detecting a potential buffer overflow ===================================== -You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. - -Overview --------- - -This topic describes how a C/C++ query for detecting a potential buffer overflow was developed. For a full overview of the topics available for learning to write queries for C/C++ code, see :doc:`CodeQL for C/C++ `. +You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. This topic describes how a C/C++ query for detecting a potential buffer overflow was developed. Problem—detecting memory allocation that omits space for a null termination character ------------------------------------------------------------------------------------- @@ -226,8 +221,8 @@ The completed query will now identify cases where the result of ``strlen`` is st where malloc.getAllocatedSize() instanceof StrlenCall select malloc, "This allocation does not include space to null-terminate the string." -What next? ----------- +Further reading +--------------- - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/csharp/dataflow.rst b/docs/language/learn-ql/csharp/dataflow.rst index e86b07c1edf..2cc60570f64 100644 --- a/docs/language/learn-ql/csharp/dataflow.rst +++ b/docs/language/learn-ql/csharp/dataflow.rst @@ -8,7 +8,6 @@ About this article This article describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries. The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. - For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Local data flow diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index 19fcbf081a5..3550c1d9329 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -253,8 +253,8 @@ Exercise 3: Write a class that represents flow sources from ``java.lang.System.g Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flows from ``getenv`` to ``java.net.URL``. (`Answer <#exercise-4>`__) -What next? ----------- +Further reading +--------------- - Try the worked examples in these articles: :doc:`Navigating the call graph ` and :doc:`Working with source locations `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. diff --git a/docs/language/learn-ql/javascript/dataflow.rst b/docs/language/learn-ql/javascript/dataflow.rst index 10903cfbd91..d8f2e2f2923 100644 --- a/docs/language/learn-ql/javascript/dataflow.rst +++ b/docs/language/learn-ql/javascript/dataflow.rst @@ -464,8 +464,8 @@ Hint: array indices are properties with numeric names; you can use regular expre Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flows from array elements of the result of a call to the ``tagName`` argument to the ``createElement`` function. (`Answer <#exercise-4>`__) -What next? ----------- +Further reading +--------------- - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index 61b172ef665..473521a9b0f 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -518,8 +518,8 @@ Type tracking is used in a few places in the standard libraries: - The `Firebase `__ and `Socket.io `__ models use type tracking to track objects coming from their respective APIs. -What next? ----------- +Further reading +--------------- - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. diff --git a/docs/language/learn-ql/writing-queries/query-metadata.rst b/docs/language/learn-ql/writing-queries/query-metadata.rst index 28c3754ca85..5d669a25389 100644 --- a/docs/language/learn-ql/writing-queries/query-metadata.rst +++ b/docs/language/learn-ql/writing-queries/query-metadata.rst @@ -1,7 +1,7 @@ Metadata for CodeQL queries =========================== -Metadata is used to tell users important information about CodeQL queries. You must include the correct query metadata in a query to be able to view query results in source code. +Metadata tells users important information about CodeQL queries. You must include the correct query metadata in a query to be able to view query results in source code. About query metadata -------------------- diff --git a/docs/language/learn-ql/writing-queries/writing-queries.rst b/docs/language/learn-ql/writing-queries/writing-queries.rst index 44f55726588..937ab6efde9 100644 --- a/docs/language/learn-ql/writing-queries/writing-queries.rst +++ b/docs/language/learn-ql/writing-queries/writing-queries.rst @@ -4,7 +4,7 @@ CodeQL queries CodeQL queries are used in code scanning analyses to find problems in source code, including potential security vulnerabilities. .. toctree:: - :maxdepth: 1 + :hidden: introduction-to-queries query-metadata @@ -13,4 +13,13 @@ CodeQL queries are used in code scanning analyses to find problems in source cod ../locations ../intro-to-data-flow path-queries - debugging-queries \ No newline at end of file + debugging-queries + +- :doc:`About CodeQL queries `: CodeQL queries are used to analyze code for issues related to security, correctness, maintainability, and readability. +- :doc:`Metadata for CodeQL queries `: Metadata tells users important information about CodeQL queries. You must include the correct query metadata in a query to be able to view query results in source code. +- :doc:`Query help files `: Query help files tell users the purpose of a query, and recommend how to solve the potential problem the query finds. +- :doc:`Defining the results of a query `: You can control how analysis results are displayed in source code by modifying a query's ``select`` statement. +- :doc:`Providing locations in CodeQL queries <../locations>`: CodeQL includes mechanisms for extracting the location of elements in a codebase. Use these mechanisms when writing custom CodeQL queries and libraries to help display information to users. +- :doc:`About data flow analysis <../intro-to-data-flow>`: Data flow analysis is used to compute the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used. +- :doc:`Creating path queries `: You can create path queries to visualize the flow of information through a codebase. +- :doc:`trouble shooting query performance `: Improve the performance of your CodeQL queries by following a few simple guidelines. From b4b1903642431b8d9af808241a8da6639f2e6265 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 27 Mar 2020 12:50:03 +0000 Subject: [PATCH 160/459] docs: simplify 'learning codeql' landing page --- docs/language/learn-ql/index.rst | 73 ++++---------------------------- 1 file changed, 9 insertions(+), 64 deletions(-) diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 4849f7816c7..8373723c73f 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -15,55 +15,13 @@ CodeQL is based on a powerful query language called QL. The following topics hel If you've previously used QL, you may notice slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. -.. toctree:: - :hidden: - - terminology-note - - -.. _getting-started: - -Getting started -*************** - -If you are new to QL, start by looking at the following topics: - .. toctree:: :maxdepth: 1 introduction-to-ql about-ql beginner/ql-tutorials - -CodeQL training and variant analysis examples -********************************************* - -To start learning how to use CodeQL for variant analysis for code written in a specific language, see: - -.. toctree:: - :maxdepth: -1 - - ql-training - -.. _writing-ql-queries: - -Writing CodeQL queries -********************** - -To learn more about writing your own queries, see: - -.. toctree:: - :maxdepth: 3 - :includehidden: - writing-queries/writing-queries - -For more information on using CodeQL to query code written in a specific language, see: - -.. toctree:: - :maxdepth: 2 - :includehidden: - cpp/ql-for-cpp csharp/ql-for-csharp cobol/ql-for-cobol @@ -71,29 +29,16 @@ For more information on using CodeQL to query code written in a specific languag java/ql-for-java javascript/ql-for-javascript python/ql-for-python - -Technical information -********************* - -For more technical information see: + ql-training + technical-info .. toctree:: - :maxdepth: 2 - :includehidden: + :hidden: + + terminology-note - technical-info +Further reading +*************** -Reference topics -**************** - -For a more comprehensive guide to the query language itself, see the following reference topics: - -- `QL language handbook `__—a description of important concepts in QL. -- `QL language specification `__—a formal specification of QL. - -Search -****** - -.. * :ref:`genindex` remove index for the time being as we currently have no tags - -* :ref:`search` +- `QL language handbook `__: A description of important concepts in QL. +- `QL language specification `__: A formal specification of QL. From a6cfdfe8e345cdf8c5c8dd53993fa1edac3b2c01 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 27 Mar 2020 12:50:50 +0000 Subject: [PATCH 161/459] docs: small change to codeql training landing page --- docs/language/learn-ql/ql-training.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index d56833ddae9..e3ada332094 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -57,9 +57,8 @@ CodeQL and variant analysis for Java - `Exercise: Apache Struts <../ql-training/java/apache-struts-java.html>`__–an example demonstrating how to develop a data flow query. - `Introduction to global data flow <../ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using CodeQL. -More resources -~~~~~~~~~~~~~~ +Further reading +~~~~~~~~~~~~~~~ - If you are completely new to CodeQL, look at our introductory topics in :doc:`Learning CodeQL `. -- To find more detailed information about how to write queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. - To see examples of CodeQL queries that have been used to find security vulnerabilities and bugs in open source software projects, visit the `GitHub Security Lab website `__ and the associated `repository `__. \ No newline at end of file From d979bd958bd194abca1ed611a447f5541ba8b26d Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 13:01:50 +0000 Subject: [PATCH 162/459] better wording for the unique aggregate --- docs/language/ql-handbook/expressions.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index e1e4a099dad..2fffc11fbee 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -281,9 +281,10 @@ The following aggregates are available in QL: .. index: unique -- ``unique``: The value of this aggregate depends on how many different values ```` can have, - within the context of a fixed set of assignments to outside variables. - If the value is uniquely determined, then the aggregate gives that value. Otherwise, it has no value. +- ``unique``: This aggregate depends on the values of ```` over all possible assignments to + the aggregation variables. If there is a unique value of the ``expression`` over the aggregation variables, + then the aggregate evaluates to that value. + Otherwise, the aggregate has no value. For example, the following aggregation yields the positive integers ``1``, ``2``, ``3``, ``4``, ``5``. For negative integers ``x``, the expressions ``x`` and ``x.abs()`` have different values and hence the From 90b82a0905321e24d7eb7ecfda8426da81a236b2 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 13:09:35 +0000 Subject: [PATCH 163/459] unique in aggregate section --- docs/language/ql-spec/language.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/language/ql-spec/language.rst b/docs/language/ql-spec/language.rst index 796fe17dfc2..e97ab84556f 100644 --- a/docs/language/ql-spec/language.rst +++ b/docs/language/ql-spec/language.rst @@ -1058,6 +1058,7 @@ An aggregation can be written in one of two forms: aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" + | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" @@ -1098,7 +1099,7 @@ The typing environment for ordering directives is obtained by taking the typing The number and types of the aggregation expressions are restricted as follows: -- A ``max``, ``min`` or ``rank`` aggregation must have a single expression. +- A ``max``, ``min``, ``rank`` or ``unique`` aggregation must have a single expression. - The type of the expression in a ``max``, ``min`` or ``rank`` aggregation without an ordering directive expression must be an orderable type. - A ``count`` or ``strictcount`` aggregation must not have an expression. - A ``sum``, ``strictsum`` or ``avg`` aggregation must have a single aggregation expression, which must have a type which is a subtype of ``float``. @@ -1140,6 +1141,8 @@ The values of the aggregation expression are given by applying the aggregation f - If the aggregation id is ``strictconcat``, then the result is the same as for ``concat`` except in the case where there are no aggregation tuples in which case the aggregation has no value. + - If the aggregation id is ``unique``, then the result is the the value of the aggregation variable if there is precisely one such value. Otherwise, the aggregation has no value. + Any ~~~ From 73845923aa9f8a2a5a9c5bc4fdc5f33b7f5d9a8c Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 13:34:20 +0000 Subject: [PATCH 164/459] Update docs/language/ql-handbook/expressions.rst Co-Authored-By: Jonas Jensen --- docs/language/ql-handbook/expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index 2fffc11fbee..cf001cd314a 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -292,7 +292,7 @@ The following aggregates are available in QL: from int x where x in [-5 .. 5] and x != 0 - select unique(int y | y = x and y = x.abs() | y) + select unique(int y | y = x or y = x.abs() | y) The ``unique`` aggregate is supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise. From 0ebbd80745bbe420e6e956ad0b4d452e8871a696 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 27 Mar 2020 14:54:34 +0100 Subject: [PATCH 165/459] autoformat --- .../ql/test/library-tests/CustomLoadStoreSteps/test.ql | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql index e7ff3a8741e..2c56d41ab4d 100644 --- a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql +++ b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql @@ -19,10 +19,14 @@ class Configuration extends TaintTracking::Configuration { ) and prop = "bar" } - + // calling .copy("foo", "bar") actually moves a property from "foo" to "bar". - override predicate isAdditionalLoadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp) { - exists(DataFlow::MethodCallNode call | call.getMethodName() = "copy" and call = succ and pred = call.getReceiver() | + override predicate isAdditionalLoadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { + exists(DataFlow::MethodCallNode call | + call.getMethodName() = "copy" and call = succ and pred = call.getReceiver() + | call.getArgument(0).mayHaveStringValue(loadProp) and call.getArgument(1).mayHaveStringValue(storeProp) ) From 5e62a6bebe8b97ba0bdb316dc2b8eff4c88b9924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Fri, 27 Mar 2020 15:10:15 +0100 Subject: [PATCH 166/459] Move CWE-036 directory to experimental --- .../src/{ => experimental}/Security/CWE/CWE-036/OpenStream.java | 0 .../src/{ => experimental}/Security/CWE/CWE-036/OpenStream.qhelp | 0 java/ql/src/{ => experimental}/Security/CWE/CWE-036/OpenStream.ql | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename java/ql/src/{ => experimental}/Security/CWE/CWE-036/OpenStream.java (100%) rename java/ql/src/{ => experimental}/Security/CWE/CWE-036/OpenStream.qhelp (100%) rename java/ql/src/{ => experimental}/Security/CWE/CWE-036/OpenStream.ql (100%) diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.java b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.java similarity index 100% rename from java/ql/src/Security/CWE/CWE-036/OpenStream.java rename to java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.java diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp similarity index 100% rename from java/ql/src/Security/CWE/CWE-036/OpenStream.qhelp rename to java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp diff --git a/java/ql/src/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql similarity index 100% rename from java/ql/src/Security/CWE/CWE-036/OpenStream.ql rename to java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql From c91c3f24a07aeeb91027ef3b11e8cd2274dbc657 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 14:47:57 +0000 Subject: [PATCH 167/459] fixed typo "the the" Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/ql-spec/language.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-spec/language.rst b/docs/language/ql-spec/language.rst index e97ab84556f..9a81728a75d 100644 --- a/docs/language/ql-spec/language.rst +++ b/docs/language/ql-spec/language.rst @@ -1141,7 +1141,7 @@ The values of the aggregation expression are given by applying the aggregation f - If the aggregation id is ``strictconcat``, then the result is the same as for ``concat`` except in the case where there are no aggregation tuples in which case the aggregation has no value. - - If the aggregation id is ``unique``, then the result is the the value of the aggregation variable if there is precisely one such value. Otherwise, the aggregation has no value. + - If the aggregation id is ``unique``, then the result is the value of the aggregation variable if there is precisely one such value. Otherwise, the aggregation has no value. Any ~~~ From 811bc01d1e9fe1dcb0cb759c99c4c39fa86be2b8 Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 14:49:23 +0000 Subject: [PATCH 168/459] the ``expression`` => ```` Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/ql-handbook/expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index cf001cd314a..90f02f79e5f 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -282,7 +282,7 @@ The following aggregates are available in QL: .. index: unique - ``unique``: This aggregate depends on the values of ```` over all possible assignments to - the aggregation variables. If there is a unique value of the ``expression`` over the aggregation variables, + the aggregation variables. If there is a unique value of ```` over the aggregation variables, then the aggregate evaluates to that value. Otherwise, the aggregate has no value. From 3406ee72eec1872169e9f13ec0a404a7ebda494b Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 14:49:45 +0000 Subject: [PATCH 169/459] Update docs/language/ql-handbook/expressions.rst Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/ql-handbook/expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index 90f02f79e5f..dc98f753856 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -279,7 +279,7 @@ The following aggregates are available in QL: evaluates to the empty set (instead of defaulting to ``0`` or the empty string). This is useful if you're only interested in results where the aggregation body is non-trivial. -.. index: unique +.. index:: unique - ``unique``: This aggregate depends on the values of ```` over all possible assignments to the aggregation variables. If there is a unique value of ```` over the aggregation variables, From 23e4ae3f49f2d05fd32c5ca880d30b3a7599eb3b Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 14:50:07 +0000 Subject: [PATCH 170/459] "and hence" => ", so" Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/ql-handbook/expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index dc98f753856..2cd47bd63e3 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -287,7 +287,7 @@ The following aggregates are available in QL: Otherwise, the aggregate has no value. For example, the following aggregation yields the positive integers ``1``, ``2``, ``3``, ``4``, ``5``. - For negative integers ``x``, the expressions ``x`` and ``x.abs()`` have different values and hence the + For negative integers ``x``, the expressions ``x`` and ``x.abs()`` have different values, so the value for ``y`` in the aggregate expression is not uniquely determined. :: from int x From a91a5c3db90057ad86e13972d86d94b2a36a2c1a Mon Sep 17 00:00:00 2001 From: Philip Ginsbach Date: Fri, 27 Mar 2020 14:50:41 +0000 Subject: [PATCH 171/459] "aggregation yields" => "query returns" Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/ql-handbook/expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index 2cd47bd63e3..0990f7a65b9 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -286,7 +286,7 @@ The following aggregates are available in QL: then the aggregate evaluates to that value. Otherwise, the aggregate has no value. - For example, the following aggregation yields the positive integers ``1``, ``2``, ``3``, ``4``, ``5``. + For example, the following query returns the positive integers ``1``, ``2``, ``3``, ``4``, ``5``. For negative integers ``x``, the expressions ``x`` and ``x.abs()`` have different values, so the value for ``y`` in the aggregate expression is not uniquely determined. :: From 3de00443fff8c094a42647ff71528e3b89ea6922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Fri, 27 Mar 2020 17:06:58 +0100 Subject: [PATCH 172/459] Review feeback for OpenStream --- .../src/experimental/Security/CWE/CWE-036/OpenStream.ql | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql index 6cf5960a55c..3b8dff2ac09 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql @@ -16,11 +16,9 @@ class URLConstructor extends ClassInstanceExpr { Expr stringArg() { // Query only in URL's that were constructed by calling the single parameter string constructor. - if - this.getConstructor().getNumberOfParameters() = 1 and - this.getConstructor().getParameter(0).getType().getName() = "String" - then result = this.getArgument(0) - else none() + this.getConstructor().getNumberOfParameters() = 1 and + this.getConstructor().getParameter(0).getType() instanceof TypeString + and result = this.getArgument(0) } } From c6688eb349874bb677beb6be3bcaa5c0966b3576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Fri, 27 Mar 2020 17:08:49 +0100 Subject: [PATCH 173/459] Fix OpenStream documentation --- .../ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp index 83ce2a6a17f..fcb7f6313ee 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp @@ -27,10 +27,12 @@ is called on the URL, potentially leading to a local file access.

    +
    • Java Platform, Standard Edition 11, API Specification: -Class URL.
    • +Class URL.
    • +
    From 90fad6f76274b1faadce8de310359f67abb82ac3 Mon Sep 17 00:00:00 2001 From: Robert Brignull Date: Fri, 27 Mar 2020 17:01:46 +0000 Subject: [PATCH 174/459] add code scanning suites --- cpp/ql/src/codeql-suites/cpp-code-scanning.qls | 4 ++++ .../src/codeql-suites/csharp-code-scanning.qls | 4 ++++ java/ql/src/codeql-suites/java-code-scanning.qls | 4 ++++ .../codeql-suites/javascript-code-scanning.qls | 4 ++++ misc/suite-helpers/code-scanning-selectors.yml | 16 ++++++++++++++++ .../src/codeql-suites/python-code-scanning.qls | 4 ++++ 6 files changed, 36 insertions(+) create mode 100644 cpp/ql/src/codeql-suites/cpp-code-scanning.qls create mode 100644 csharp/ql/src/codeql-suites/csharp-code-scanning.qls create mode 100644 java/ql/src/codeql-suites/java-code-scanning.qls create mode 100644 javascript/ql/src/codeql-suites/javascript-code-scanning.qls create mode 100644 misc/suite-helpers/code-scanning-selectors.yml create mode 100644 python/ql/src/codeql-suites/python-code-scanning.qls diff --git a/cpp/ql/src/codeql-suites/cpp-code-scanning.qls b/cpp/ql/src/codeql-suites/cpp-code-scanning.qls new file mode 100644 index 00000000000..27bff98ea5d --- /dev/null +++ b/cpp/ql/src/codeql-suites/cpp-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for C and C++ +- qlpack: codeql-cpp +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/csharp/ql/src/codeql-suites/csharp-code-scanning.qls b/csharp/ql/src/codeql-suites/csharp-code-scanning.qls new file mode 100644 index 00000000000..3646204da7d --- /dev/null +++ b/csharp/ql/src/codeql-suites/csharp-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for C# +- qlpack: codeql-csharp +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/java/ql/src/codeql-suites/java-code-scanning.qls b/java/ql/src/codeql-suites/java-code-scanning.qls new file mode 100644 index 00000000000..7dc29ab8049 --- /dev/null +++ b/java/ql/src/codeql-suites/java-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for Java +- qlpack: codeql-java +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/javascript/ql/src/codeql-suites/javascript-code-scanning.qls b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls new file mode 100644 index 00000000000..f87a55157a2 --- /dev/null +++ b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for JavaScript +- qlpack: codeql-javascript +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/misc/suite-helpers/code-scanning-selectors.yml b/misc/suite-helpers/code-scanning-selectors.yml new file mode 100644 index 00000000000..ffa40d8e4b1 --- /dev/null +++ b/misc/suite-helpers/code-scanning-selectors.yml @@ -0,0 +1,16 @@ +- description: Selectors for selecting the Code-Scanning-relevant queries for a language +- include: + kind: + - problem + - path-problem + precision: + - high + - very-high + problem.severity: + - error + - warning + tags contain: + - security +- exclude: + deprecated: // + diff --git a/python/ql/src/codeql-suites/python-code-scanning.qls b/python/ql/src/codeql-suites/python-code-scanning.qls new file mode 100644 index 00000000000..f9f9a5425b6 --- /dev/null +++ b/python/ql/src/codeql-suites/python-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for Python +- qlpack: codeql-python +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers From 69041bc959449e16012255be8c3ce092476378d9 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Thu, 26 Mar 2020 20:39:31 +0000 Subject: [PATCH 175/459] C#: Enable nullability in Autobuilder. --- .../Semmle.Autobuild.Tests/BuildScripts.cs | 5 +- .../Semmle.Autobuild/AspBuildRule.cs | 7 +- .../Semmle.Autobuild/AutobuildOptions.cs | 54 ++++++++------- .../Semmle.Autobuild/Autobuilder.cs | 66 ++++++++++++++----- .../Semmle.Autobuild/BuildActions.cs | 14 ++-- .../Semmle.Autobuild/BuildCommandAutoRule.cs | 2 +- .../Semmle.Autobuild/BuildScript.cs | 24 ++++--- .../Semmle.Autobuild/CommandBuilder.cs | 26 +++++--- .../Semmle.Autobuild/DotNetRule.cs | 20 +++--- .../Semmle.Autobuild/MsBuildRule.cs | 8 +-- .../autobuilder/Semmle.Autobuild/Program.cs | 22 ++++--- .../autobuilder/Semmle.Autobuild/Project.cs | 2 +- .../Semmle.Autobuild/ProjectOrSolution.cs | 3 + .../Semmle.Autobuild/Semmle.Autobuild.csproj | 1 + .../autobuilder/Semmle.Autobuild/Solution.cs | 4 +- .../Semmle.Autobuild/StandaloneBuildRule.cs | 9 +-- .../Semmle.Autobuild/XmlBuildRule.cs | 2 +- .../Semmle.Util.Tests.csproj | 1 + 18 files changed, 168 insertions(+), 102 deletions(-) diff --git a/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs index a2e59cf7ac3..b66fa4ff399 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs @@ -341,6 +341,8 @@ namespace Semmle.Extraction.Tests string cwd = @"C:\Project") { Actions.GetEnvironmentVariable["CODEQL_AUTOBUILDER_CSHARP_NO_INDEXING"] = "false"; + Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = ""; + Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = ""; Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_ROOT"] = @"C:\codeql\csharp"; Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java"; Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa"; @@ -364,8 +366,7 @@ namespace Semmle.Extraction.Tests Actions.GetCurrentDirectory = cwd; Actions.IsWindows = isWindows; - var options = new AutobuildOptions(); - options.ReadEnvironment(Actions); + var options = new AutobuildOptions(Actions); return new Autobuilder(Actions, options); } diff --git a/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs index b5b3dfcf61d..f9c690c273b 100644 --- a/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs @@ -7,10 +7,9 @@ { public BuildScript Analyse(Autobuilder builder, bool auto) { - (var javaHome, var dist) = - builder.CodeQLJavaHome != null ? - (builder.CodeQLJavaHome, builder.CodeQLExtractorCSharpRoot) : - (builder.SemmleJavaHome, builder.SemmleDist); + var javaHome = builder.JavaHome; + var dist = builder.Distribution; + var command = new CommandBuilder(builder.Actions). RunCommand(builder.Actions.PathCombine(javaHome, "bin", "java")). Argument("-jar"). diff --git a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs index 740b740f9fb..e89ca1a4663 100644 --- a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs @@ -10,40 +10,40 @@ namespace Semmle.Autobuild public class AutobuildOptions { public readonly int SearchDepth = 3; - public string RootDirectory = null; - static readonly string prefix = "LGTM_INDEX_"; + public readonly string RootDirectory; + private const string prefix = "LGTM_INDEX_"; - public string VsToolsVersion; - public string MsBuildArguments; - public string MsBuildPlatform; - public string MsBuildConfiguration; - public string MsBuildTarget; - public string DotNetArguments; - public string DotNetVersion; - public string BuildCommand; - public string[] Solution; + public readonly string? VsToolsVersion; + public readonly string? MsBuildArguments; + public readonly string? MsBuildPlatform; + public readonly string? MsBuildConfiguration; + public readonly string? MsBuildTarget; + public readonly string? DotNetArguments; + public readonly string? DotNetVersion; + public readonly string? BuildCommand; + public readonly string[] Solution; - public bool IgnoreErrors; - public bool Buildless; - public bool AllSolutions; - public bool NugetRestore; + public readonly bool IgnoreErrors; + public readonly bool Buildless; + public readonly bool AllSolutions; + public readonly bool NugetRestore; - public Language Language; - public bool Indexing; + public readonly Language Language; + public readonly bool Indexing; /// /// Reads options from environment variables. /// Throws ArgumentOutOfRangeException for invalid arguments. /// - public void ReadEnvironment(IBuildActions actions) + public AutobuildOptions(IBuildActions actions) { RootDirectory = actions.GetCurrentDirectory(); VsToolsVersion = actions.GetEnvironmentVariable(prefix + "VSTOOLS_VERSION"); - MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS").AsStringWithExpandedEnvVars(actions); + MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS").AsStringWithExpandedEnvVarsMaybeNull(actions); MsBuildPlatform = actions.GetEnvironmentVariable(prefix + "MSBUILD_PLATFORM"); MsBuildConfiguration = actions.GetEnvironmentVariable(prefix + "MSBUILD_CONFIGURATION"); MsBuildTarget = actions.GetEnvironmentVariable(prefix + "MSBUILD_TARGET"); - DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS").AsStringWithExpandedEnvVars(actions); + DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS").AsStringWithExpandedEnvVarsMaybeNull(actions); DotNetVersion = actions.GetEnvironmentVariable(prefix + "DOTNET_VERSION"); BuildCommand = actions.GetEnvironmentVariable(prefix + "BUILD_COMMAND"); Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsListWithExpandedEnvVars(actions, new string[0]); @@ -60,7 +60,7 @@ namespace Semmle.Autobuild public static class OptionsExtensions { - public static bool AsBool(this string value, string param, bool defaultValue) + public static bool AsBool(this string? value, string param, bool defaultValue) { if (value == null) return defaultValue; switch (value.ToLower()) @@ -80,7 +80,7 @@ namespace Semmle.Autobuild } } - public static Language AsLanguage(this string key) + public static Language AsLanguage(this string? key) { switch (key) { @@ -95,7 +95,7 @@ namespace Semmle.Autobuild } } - public static string[] AsListWithExpandedEnvVars(this string value, IBuildActions actions, string[] defaultValue) + public static string[] AsListWithExpandedEnvVars(this string? value, IBuildActions actions, string[] defaultValue) { if (value == null) return defaultValue; @@ -107,6 +107,14 @@ namespace Semmle.Autobuild static readonly Regex linuxEnvRegEx = new Regex(@"\$([a-zA-Z_][a-zA-Z_0-9]*)", RegexOptions.Compiled); + public static string? AsStringWithExpandedEnvVarsMaybeNull(this string? value, IBuildActions actions) + { + if (string.IsNullOrEmpty(value)) + return value; + + return value.AsStringWithExpandedEnvVars(actions); + } + public static string AsStringWithExpandedEnvVars(this string value, IBuildActions actions) { if (string.IsNullOrEmpty(value)) diff --git a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs index 73e6fcd181f..3eda9a0473e 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs @@ -20,6 +20,14 @@ namespace Semmle.Autobuild BuildScript Analyse(Autobuilder builder, bool auto); } + /// + /// Exception indicating that environment variables are missing or invalid. + /// + class InvalidEnvironmentException : Exception + { + public InvalidEnvironmentException(string m) : base(m) { } + } + /// /// Main application logic, containing all data /// gathered from the project and filesystem. @@ -69,7 +77,7 @@ namespace Semmle.Autobuild /// List of project/solution files to build. /// public IList ProjectsOrSolutionsToBuild => projectsOrSolutionsToBuildLazy.Value; - readonly Lazy> projectsOrSolutionsToBuildLazy; + private readonly Lazy> projectsOrSolutionsToBuildLazy; ///
    /// Holds if a given path was found. @@ -129,7 +137,7 @@ namespace Semmle.Autobuild projectsOrSolutionsToBuildLazy = new Lazy>(() => { - List ret; + List? ret; if (options.Solution.Any()) { ret = new List(); @@ -143,7 +151,7 @@ namespace Semmle.Autobuild return ret; } - IEnumerable FindFiles(string extension, Func create) + IEnumerable? FindFiles(string extension, Func create) { var matchingFiles = GetExtensions(extension). Select(p => (ProjectOrSolution: create(p.Item1), DistanceFromRoot: p.Item2)). @@ -178,18 +186,39 @@ namespace Semmle.Autobuild CodeQLExtractorCSharpRoot = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_ROOT"); - CodeQLJavaHome = Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME"); - SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST"); + CodeQLJavaHome = Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME"); + SemmleJavaHome = Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME"); + if(CodeQLJavaHome is null && SemmleJavaHome is null) + throw new InvalidEnvironmentException("The environment variables CODEQL_JAVA_HOME and SEMMLE_JAVA_HOME have not been set."); + SemmlePlatformTools = Actions.GetEnvironmentVariable("SEMMLE_PLATFORM_TOOLS"); - if (CodeQLExtractorCSharpRoot == null && SemmleDist == null) - Log(Severity.Error, "The environment variables CODEQL_EXTRACTOR_CSHARP_ROOT and SEMMLE_DIST have not been set."); + if (CodeQLExtractorCSharpRoot is null && SemmleDist is null) + throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_ROOT and SEMMLE_DIST have not been set."); + + var trapDir = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? Actions.GetEnvironmentVariable("TRAP_FOLDER"); + + if (trapDir is null) + throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_TRAP_DIR and TRAP_FOLDER have not been set."); + + TrapDir = trapDir; + + var sourceArchiveDir = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? Actions.GetEnvironmentVariable("SOURCE_ARCHIVE"); + + if(sourceArchiveDir is null) + throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR and SOURCE_ARCHIVE have not been set."); + + SourceArchiveDir = sourceArchiveDir; } + private string TrapDir { get; } + + private string SourceArchiveDir { get; } + readonly ILogger logger = new ConsoleLogger(Verbosity.Info); /// @@ -271,9 +300,9 @@ namespace Semmle.Autobuild break; case CSharpBuildStrategy.Auto: var cleanTrapFolder = - BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? Actions.GetEnvironmentVariable("TRAP_FOLDER")); + BuildScript.DeleteDirectory(TrapDir); var cleanSourceArchive = - BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? Actions.GetEnvironmentVariable("SOURCE_ARCHIVE")); + BuildScript.DeleteDirectory(SourceArchiveDir); var tryCleanExtractorArgsLogs = BuildScript.Create(actions => { @@ -376,38 +405,43 @@ namespace Semmle.Autobuild /// /// Value of CODEQL_EXTRACTOR_CSHARP_ROOT environment variable. /// - public string CodeQLExtractorCSharpRoot { get; private set; } + private string? CodeQLExtractorCSharpRoot { get; } /// /// Value of CODEQL_JAVA_HOME environment variable. /// - public string CodeQLJavaHome { get; private set; } + private string? CodeQLJavaHome { get; } /// /// Value of SEMMLE_DIST environment variable. /// - public string SemmleDist { get; private set; } + private string? SemmleDist { get; } + + public string Distribution => CodeQLExtractorCSharpRoot ?? SemmleDist!; + + public string JavaHome => CodeQLJavaHome ?? SemmleJavaHome!; /// /// Value of SEMMLE_JAVA_HOME environment variable. /// - public string SemmleJavaHome { get; private set; } + public string? SemmleJavaHome { get; private set; } /// /// Value of SEMMLE_PLATFORM_TOOLS environment variable. /// - public string SemmlePlatformTools { get; private set; } + public string? SemmlePlatformTools { get; private set; } /// /// The absolute path of the odasa executable. + /// null if we are running in CodeQL. /// - public string Odasa => SemmleDist == null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa"); + public string? Odasa => SemmleDist is null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa"); /// /// Construct a command that executed the given wrapped in /// an odasa --index, unless indexing has been disabled, in which case /// is run directly. /// - internal CommandBuilder MaybeIndex(CommandBuilder builder, string cmd) => Options.Indexing ? builder.IndexCommand(Odasa, cmd) : builder.RunCommand(cmd); + internal CommandBuilder MaybeIndex(CommandBuilder builder, string cmd) => Options.Indexing && !(Odasa is null) ? builder.IndexCommand(Odasa, cmd) : builder.RunCommand(cmd); } } diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs index 837f6e3f69e..7bc4b9b7591 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs @@ -21,7 +21,7 @@ namespace Semmle.Autobuild /// Additional environment variables. /// The lines of stdout. /// The process exit code. - int RunProcess(string exe, string args, string workingDirectory, IDictionary env, out IList stdOut); + int RunProcess(string exe, string args, string? workingDirectory, IDictionary? env, out IList stdOut); /// /// Runs a process but does not capture its output. @@ -31,7 +31,7 @@ namespace Semmle.Autobuild /// The working directory (null for current directory). /// Additional environment variables. /// The process exit code. - int RunProcess(string exe, string args, string workingDirectory, IDictionary env); + int RunProcess(string exe, string args, string? workingDirectory, IDictionary? env); /// /// Tests whether a file exists, File.Exists(). @@ -63,7 +63,7 @@ namespace Semmle.Autobuild /// /// The name of the variable. /// The string value, or null if the variable is not defined. - string GetEnvironmentVariable(string name); + string? GetEnvironmentVariable(string name); /// /// Gets the current directory, Directory.GetCurrentDirectory(). @@ -130,7 +130,7 @@ namespace Semmle.Autobuild bool IBuildActions.FileExists(string file) => File.Exists(file); - ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string workingDirectory, IDictionary environment, bool redirectStandardOutput) + ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string? workingDirectory, IDictionary? environment, bool redirectStandardOutput) { var pi = new ProcessStartInfo(exe, arguments) { @@ -146,7 +146,7 @@ namespace Semmle.Autobuild return pi; } - int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary environment) + int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary? environment) { var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false); using (var p = Process.Start(pi)) @@ -156,7 +156,7 @@ namespace Semmle.Autobuild } } - int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary environment, out IList stdOut) + int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary? environment, out IList stdOut) { var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, true); return pi.ReadOutput(out stdOut); @@ -166,7 +166,7 @@ namespace Semmle.Autobuild bool IBuildActions.DirectoryExists(string dir) => Directory.Exists(dir); - string IBuildActions.GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name); + string? IBuildActions.GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name); string IBuildActions.GetCurrentDirectory() => Directory.GetCurrentDirectory(); diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs b/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs index e7e2c9255dd..80a819f403e 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs @@ -40,7 +40,7 @@ namespace Semmle.Autobuild chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}"); var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script); - var dir = Path.GetDirectoryName(scriptPath); + string? dir = Path.GetDirectoryName(scriptPath); // A specific .NET Core version may be required return chmodScript & DotNetRule.WithDotNet(builder, environment => diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs index 93ea941d58b..5c60f4110ba 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs @@ -48,8 +48,9 @@ namespace Semmle.Autobuild class BuildCommand : BuildScript { - readonly string exe, arguments, workingDirectory; - readonly IDictionary environment; + readonly string exe, arguments; + readonly string? workingDirectory; + readonly IDictionary? environment; readonly bool silent; /// @@ -60,7 +61,7 @@ namespace Semmle.Autobuild /// Whether this command should run silently. /// The working directory (null for current directory). /// Additional environment variables. - public BuildCommand(string exe, string argumentsOpt, bool silent, string workingDirectory = null, IDictionary environment = null) + public BuildCommand(string exe, string argumentsOpt, bool silent, string? workingDirectory = null, IDictionary? environment = null) { this.exe = exe; this.arguments = argumentsOpt ?? ""; @@ -131,8 +132,8 @@ namespace Semmle.Autobuild class BindBuildScript : BuildScript { readonly BuildScript s1; - readonly Func, int, BuildScript> s2a; - readonly Func s2b; + readonly Func, int, BuildScript>? s2a; + readonly Func? s2b; public BindBuildScript(BuildScript s1, Func, int, BuildScript> s2) { this.s1 = s1; @@ -154,14 +155,19 @@ namespace Semmle.Autobuild return s2a(stdout1, ret1).Run(actions, startCallback, exitCallBack); } - ret1 = s1.Run(actions, startCallback, exitCallBack); - return s2b(ret1).Run(actions, startCallback, exitCallBack); + if (s2b != null) + { + ret1 = s1.Run(actions, startCallback, exitCallBack); + return s2b(ret1).Run(actions, startCallback, exitCallBack); + } + + throw new InvalidOperationException("Unexpected error"); } public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) { var ret1 = s1.Run(actions, startCallback, exitCallBack, out var stdout1); - var ret2 = (s2a != null ? s2a(stdout1, ret1) : s2b(ret1)).Run(actions, startCallback, exitCallBack, out var stdout2); + var ret2 = (s2a != null ? s2a(stdout1, ret1) : s2b!(ret1)).Run(actions, startCallback, exitCallBack, out var stdout2); var @out = new List(); @out.AddRange(stdout1); @out.AddRange(stdout2); @@ -177,7 +183,7 @@ namespace Semmle.Autobuild /// Whether the executable should run silently. /// The working directory (null for current directory). /// Additional environment variables. - public static BuildScript Create(string exe, string argumentsOpt, bool silent, string workingDirectory, IDictionary environment) => + public static BuildScript Create(string exe, string argumentsOpt, bool silent, string? workingDirectory, IDictionary? environment) => new BuildCommand(exe, argumentsOpt, silent, workingDirectory, environment); /// diff --git a/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs b/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs index 7b95e495697..444865400f4 100644 --- a/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs @@ -13,10 +13,10 @@ namespace Semmle.Autobuild readonly StringBuilder arguments; bool firstCommand; - string executable; + string? executable; readonly EscapeMode escapingMode; - readonly string workingDirectory; - readonly IDictionary environment; + readonly string? workingDirectory; + readonly IDictionary? environment; readonly bool silent; /// @@ -25,7 +25,7 @@ namespace Semmle.Autobuild /// The working directory (null for current directory). /// Additional environment variables. /// Whether this command should be run silently. - public CommandBuilder(IBuildActions actions, string workingDirectory = null, IDictionary environment = null, bool silent = false) + public CommandBuilder(IBuildActions actions, string? workingDirectory = null, IDictionary? environment = null, bool silent = false) { arguments = new StringBuilder(); if (actions.IsWindows()) @@ -50,7 +50,7 @@ namespace Semmle.Autobuild RunCommand(odasa, "index --auto"); } - public CommandBuilder CallBatFile(string batFile, string argumentsOpt = null) + public CommandBuilder CallBatFile(string batFile, string? argumentsOpt = null) { NextCommand(); arguments.Append(" CALL"); @@ -66,7 +66,7 @@ namespace Semmle.Autobuild /// The command to run. /// Additional arguments. /// this for chaining calls. - public CommandBuilder IndexCommand(string odasa, string command, string argumentsOpt = null) + public CommandBuilder IndexCommand(string odasa, string command, string? argumentsOpt = null) { OdasaIndex(odasa); QuoteArgument(command); @@ -151,7 +151,7 @@ namespace Semmle.Autobuild arguments.Append(' '); } - public CommandBuilder Argument(string argumentsOpt) + public CommandBuilder Argument(string? argumentsOpt) { if (argumentsOpt != null) { @@ -169,7 +169,7 @@ namespace Semmle.Autobuild arguments.Append(" &&"); } - public CommandBuilder RunCommand(string exe, string argumentsOpt = null) + public CommandBuilder RunCommand(string exe, string? argumentsOpt = null) { var (exe0, arg0) = escapingMode == EscapeMode.Process && exe.EndsWith(".exe", System.StringComparison.Ordinal) @@ -193,6 +193,14 @@ namespace Semmle.Autobuild /// /// Returns a build script that contains just this command. /// - public BuildScript Script => BuildScript.Create(executable, arguments.ToString(), silent, workingDirectory, environment); + public BuildScript Script + { + get + { + if (executable is null) + throw new System.InvalidOperationException("executable is null"); + return BuildScript.Create(executable, arguments.ToString(), silent, workingDirectory, environment); + } + } } } diff --git a/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs index f3b81665fca..21215af8434 100644 --- a/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs @@ -56,13 +56,13 @@ namespace Semmle.Autobuild }); } - static BuildScript WithDotNet(Autobuilder builder, Func, bool, BuildScript> f) + static BuildScript WithDotNet(Autobuilder builder, Func?, bool, BuildScript> f) { - var installDir = builder.Actions.PathCombine(builder.Options.RootDirectory, ".dotnet"); + string? installDir = builder.Actions.PathCombine(builder.Options.RootDirectory, ".dotnet"); var installScript = DownloadDotNet(builder, installDir); return BuildScript.Bind(installScript, installed => { - Dictionary env; + Dictionary? env; if (installed == 0) { // The installation succeeded, so use the newly installed .NET Core @@ -120,7 +120,7 @@ namespace Semmle.Autobuild /// variables needed by the installed .NET Core (null when no variables /// are needed). /// - public static BuildScript WithDotNet(Autobuilder builder, Func, BuildScript> f) + public static BuildScript WithDotNet(Autobuilder builder, Func?, BuildScript> f) => WithDotNet(builder, (_1, env, _2) => f(env)); /// @@ -265,10 +265,10 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return listSdks.Script; } - static string DotNetCommand(IBuildActions actions, string dotNetPath) => + static string DotNetCommand(IBuildActions actions, string? dotNetPath) => dotNetPath != null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet"; - BuildScript GetInfoCommand(IBuildActions actions, string dotNetPath, IDictionary environment) + BuildScript GetInfoCommand(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var info = new CommandBuilder(actions, null, environment). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -276,7 +276,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return info.Script; } - CommandBuilder GetCleanCommand(IBuildActions actions, string dotNetPath, IDictionary environment) + CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var clean = new CommandBuilder(actions, null, environment). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -284,7 +284,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return clean; } - CommandBuilder GetRestoreCommand(IBuildActions actions, string dotNetPath, IDictionary environment) + CommandBuilder GetRestoreCommand(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var restore = new CommandBuilder(actions, null, environment). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -292,7 +292,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return restore; } - static BuildScript GetInstalledRuntimesScript(IBuildActions actions, string dotNetPath, IDictionary environment) + static BuildScript GetInstalledRuntimesScript(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var listSdks = new CommandBuilder(actions, environment: environment, silent: true). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -309,7 +309,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; /// hence the need for CLR tracing), by adding a /// `/p:UseSharedCompilation=false` argument. /// - BuildScript GetBuildScript(Autobuilder builder, string dotNetPath, IDictionary environment, bool compatibleClr, string projOrSln) + BuildScript GetBuildScript(Autobuilder builder, string? dotNetPath, IDictionary? environment, bool compatibleClr, string projOrSln) { var build = new CommandBuilder(builder.Actions, null, environment); var script = builder.MaybeIndex(build, DotNetCommand(builder.Actions, dotNetPath)). diff --git a/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs index b0ee01b8d3c..f9ef06feb08 100644 --- a/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs @@ -67,10 +67,10 @@ namespace Semmle.Autobuild string target = builder.Options.MsBuildTarget != null ? builder.Options.MsBuildTarget : "rebuild"; - string platform = builder.Options.MsBuildPlatform != null + string? platform = builder.Options.MsBuildPlatform != null ? builder.Options.MsBuildPlatform : projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null; - string configuration = builder.Options.MsBuildConfiguration != null + string? configuration = builder.Options.MsBuildConfiguration != null ? builder.Options.MsBuildConfiguration : projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null; @@ -96,9 +96,9 @@ namespace Semmle.Autobuild /// /// Returns null when no version is specified. /// - public static VcVarsBatFile GetVcVarsBatFile(Autobuilder builder) + public static VcVarsBatFile? GetVcVarsBatFile(Autobuilder builder) { - VcVarsBatFile vsTools = null; + VcVarsBatFile? vsTools = null; if (builder.Options.VsToolsVersion != null) { diff --git a/csharp/autobuilder/Semmle.Autobuild/Program.cs b/csharp/autobuilder/Semmle.Autobuild/Program.cs index c4542864a09..e4bccb0e626 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Program.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Program.cs @@ -6,23 +6,27 @@ namespace Semmle.Autobuild { static int Main() { - var options = new AutobuildOptions(); - var actions = SystemBuildActions.Instance; try { - options.ReadEnvironment(actions); + var actions = SystemBuildActions.Instance; + var options = new AutobuildOptions(actions); + try + { + Console.WriteLine($"Semmle autobuilder for {options.Language}"); + var builder = new Autobuilder(actions, options); + return builder.AttemptBuild(); + } + catch(InvalidEnvironmentException ex) + { + Console.WriteLine("The environment is invalid: {0}", ex.Message); + } } catch (ArgumentOutOfRangeException ex) { Console.WriteLine("The value \"{0}\" for parameter \"{1}\" is invalid", ex.ActualValue, ex.ParamName); } - - var builder = new Autobuilder(actions, options); - - Console.WriteLine($"Semmle autobuilder for {options.Language}"); - - return builder.AttemptBuild(); + return 1; } } } diff --git a/csharp/autobuilder/Semmle.Autobuild/Project.cs b/csharp/autobuilder/Semmle.Autobuild/Project.cs index 0080f170c54..415ddcbc0f0 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Project.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Project.cs @@ -82,7 +82,7 @@ namespace Semmle.Autobuild foreach (var include in projectFileIncludes.Concat(projectFilesIncludes)) { var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries)); - ret.Add(new Project(builder, builder.Actions.PathCombine(Path.GetDirectoryName(this.FullPath), includePath))); + ret.Add(new Project(builder, builder.Actions.PathCombine(DirectoryName, includePath))); } return ret; }); diff --git a/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs b/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs index 53025345b69..13859a8c0eb 100644 --- a/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs +++ b/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; using System.Linq; namespace Semmle.Autobuild @@ -24,6 +25,8 @@ namespace Semmle.Autobuild { public string FullPath { get; private set; } + public string DirectoryName => Path.GetDirectoryName(FullPath) ?? ""; + protected ProjectOrSolution(Autobuilder builder, string path) { FullPath = builder.Actions.GetFullPath(path); diff --git a/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj b/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj index 5e3f2295ad0..63aab3b29fb 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj +++ b/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj @@ -9,6 +9,7 @@ false win-x64;linux-x64;osx-x64 + enable diff --git a/csharp/autobuilder/Semmle.Autobuild/Solution.cs b/csharp/autobuilder/Semmle.Autobuild/Solution.cs index 661f46199f8..0429b9f420c 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Solution.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Solution.cs @@ -43,7 +43,7 @@ namespace Semmle.Autobuild /// class Solution : ProjectOrSolution, ISolution { - readonly SolutionFile solution; + readonly SolutionFile? solution; readonly IEnumerable includedProjects; public override IEnumerable IncludedProjects => includedProjects; @@ -81,7 +81,7 @@ namespace Semmle.Autobuild includedProjects = solution.ProjectsInOrder. Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat). - Select(p => builder.Actions.PathCombine(Path.GetDirectoryName(path), builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries)))). + Select(p => builder.Actions.PathCombine(DirectoryName, builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries)))). Select(p => new Project(builder, p)). ToArray(); } diff --git a/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs index 366ce1f08fc..26bc84bb601 100644 --- a/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs @@ -1,6 +1,4 @@ -using System.IO; - -namespace Semmle.Autobuild +namespace Semmle.Autobuild { /// /// Build using standalone extraction. @@ -9,8 +7,11 @@ namespace Semmle.Autobuild { public BuildScript Analyse(Autobuilder builder, bool auto) { - BuildScript GetCommand(string solution) + BuildScript GetCommand(string? solution) { + if (builder.SemmlePlatformTools is null) + return BuildScript.Failure; + var standalone = builder.Actions.PathCombine(builder.SemmlePlatformTools, "csharp", "Semmle.Extraction.CSharp.Standalone"); var cmd = new CommandBuilder(builder.Actions); cmd.RunCommand(standalone); diff --git a/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs index 5814c2b63d2..d9b05dbe0a9 100644 --- a/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs @@ -7,7 +7,7 @@ { public BuildScript Analyse(Autobuilder builder, bool auto) { - if (!builder.Options.Indexing) + if (!builder.Options.Indexing || builder.Odasa is null) return BuildScript.Success; var command = new CommandBuilder(builder.Actions). diff --git a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj index d0ef95a4d4c..a82997aea63 100644 --- a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj +++ b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj @@ -5,6 +5,7 @@ netcoreapp3.0 false win-x64;linux-x64;osx-x64 + enable From c3a6ca0d9a069b9efadc9a909e14feccb8377f9b Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Fri, 27 Mar 2020 18:08:14 -0400 Subject: [PATCH 176/459] C++: Better support for complex numbers in IR and AST This PR adds better support for differentiating complex and imaginary floating-point types from real floating-point types, in both the AST and in the IR type system. *AST Changes* - Introduces the new class `TypeDomain`, which can be either `RealDomain`, `ImaginaryDomain` or `ComplexDomain`. "type domain" is the term used for this concept in the C standard, and I couldn't think of a better one. - Introduces `FloatingPointType.getDomain()`, to get the type domain of the type. - Introduces `FloatingPointType.getBase()`, to get the numeric base of the type (either 2 or 10). - Introduces three new subtypes of `FloatingPointType`: `RealNumberType`, `ComplexNumberType`, and `ImaginaryNumberType`, which differentiate between the types based on their type domain. Note that the decimal types (e.g., `_Decimal32`) are included in `RealNumberType`. - Introduces two new subtypes of `FloatingPointType`: `BinaryFloatingPointType` and `DecimalFloatingPointType`, which differentiate between the types based on their numeric base, independent of type domain. *IR Changes* - `IRFloatingPointType` now has two additional parameters: the base and the type domain. - New test that ensures that C++ types get mapped to the correct IR types. - New IR test that verifies the IR for some basic usage of complex FP types. --- cpp/ql/src/semmle/code/cpp/Type.qll | 201 ++++++++++++++++-- .../code/cpp/ir/implementation/IRType.qll | 43 +++- .../semmle/code/cpp/ir/internal/CppType.qll | 44 +++- .../code/cpp/ir/internal/IRCppLanguage.qll | 5 + .../library-tests/ir/ir/PrintAST.expected | 56 +++++ cpp/ql/test/library-tests/ir/ir/complex.c | 5 + .../test/library-tests/ir/ir/raw_ir.expected | 33 +++ cpp/ql/test/library-tests/ir/types/complex.c | 6 + .../test/library-tests/ir/types/irtypes.cpp | 65 ++++++ .../library-tests/ir/types/irtypes.expected | 0 cpp/ql/test/library-tests/ir/types/irtypes.ql | 18 ++ .../code/csharp/ir/implementation/IRType.qll | 43 +++- .../code/csharp/ir/internal/CSharpType.qll | 14 +- .../csharp/ir/internal/IRCSharpLanguage.qll | 37 ++++ 14 files changed, 526 insertions(+), 44 deletions(-) create mode 100644 cpp/ql/test/library-tests/ir/ir/complex.c create mode 100644 cpp/ql/test/library-tests/ir/types/complex.c create mode 100644 cpp/ql/test/library-tests/ir/types/irtypes.cpp create mode 100644 cpp/ql/test/library-tests/ir/types/irtypes.expected create mode 100644 cpp/ql/test/library-tests/ir/types/irtypes.ql diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index 38e5efba6df..f6787d00e1a 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -697,28 +697,187 @@ class Int128Type extends IntegralType { override string getCanonicalQLClass() { result = "Int128Type" } } +private newtype TTypeDomain = + TRealDomain() or + TComplexDomain() or + TImaginaryDomain() + /** - * The C/C++ floating point types. See 4.5. This includes `float`, - * `double` and `long double` types. - * ``` - * float f; - * double d; - * long double ld; - * ``` + * The type domain of a floating-point type. One of `RealDomain`, `ComplexDomain`, or + * `ImaginaryDomain`. + */ +class TypeDomain extends TTypeDomain { + string toString() { none() } +} + +/** + * The type domain of a floating-point type that represents a real number. + */ +class RealDomain extends TypeDomain, TRealDomain { + final override string toString() { result = "real" } +} + +/** + * The type domain of a floating-point type that represents a complex number. + */ +class ComplexDomain extends TypeDomain, TComplexDomain { + final override string toString() { result = "complex" } +} + +/** + * The type domain of a floating-point type that represents an imaginary number. + */ +class ImaginaryDomain extends TypeDomain, TImaginaryDomain { + final override string toString() { result = "imaginary" } +} + +/** + * Data for floating-point types. + * + * kind: The original type kind. Can be any floating-point type kind. + * base: The numeric base of the number's representation. Can be 2 (binary) or 10 (decimal). + * domain: The type domain of the type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + * realKind: The type kind of the corresponding real type. For example, the corresponding real type + * of `_Complex double` is `double`. + * extended: `true` if the number is an extended-precision floating-point number, such as + * `_Float32x`. + */ +private predicate floatingPointTypeMapping( + int kind, int base, TTypeDomain domain, int realKind, boolean extended +) { + // float + kind = 24 and base = 2 and domain = TRealDomain() and realKind = 24 and extended = false + or + // double + kind = 25 and base = 2 and domain = TRealDomain() and realKind = 25 and extended = false + or + // long double + kind = 26 and base = 2 and domain = TRealDomain() and realKind = 26 and extended = false + or + // _Complex float + kind = 27 and base = 2 and domain = TComplexDomain() and realKind = 24 and extended = false + or + // _Complex double + kind = 28 and base = 2 and domain = TComplexDomain() and realKind = 25 and extended = false + or + // _Complex long double + kind = 29 and base = 2 and domain = TComplexDomain() and realKind = 26 and extended = false + or + // _Imaginary float + kind = 30 and base = 2 and domain = TImaginaryDomain() and realKind = 24 and extended = false + or + // _Imaginary double + kind = 31 and base = 2 and domain = TImaginaryDomain() and realKind = 25 and extended = false + or + // _Imaginary long double + kind = 32 and base = 2 and domain = TImaginaryDomain() and realKind = 26 and extended = false + or + // __float128 + kind = 38 and base = 2 and domain = TRealDomain() and realKind = 38 and extended = false + or + // _Complex __float128 + kind = 39 and base = 2 and domain = TComplexDomain() and realKind = 38 and extended = false + or + // _Decimal32 + kind = 40 and base = 10 and domain = TRealDomain() and realKind = 40 and extended = false + or + // _Decimal64 + kind = 41 and base = 10 and domain = TRealDomain() and realKind = 41 and extended = false + or + // _Decimal128 + kind = 42 and base = 10 and domain = TRealDomain() and realKind = 42 and extended = false + or + // _Float32 + kind = 45 and base = 2 and domain = TRealDomain() and realKind = 45 and extended = false + or + // _Float32x + kind = 46 and base = 2 and domain = TRealDomain() and realKind = 46 and extended = true + or + // _Float64 + kind = 47 and base = 2 and domain = TRealDomain() and realKind = 47 and extended = false + or + // _Float64x + kind = 48 and base = 2 and domain = TRealDomain() and realKind = 48 and extended = true + or + // _Float128 + kind = 49 and base = 2 and domain = TRealDomain() and realKind = 49 and extended = false + or + // _Float128x + kind = 50 and base = 2 and domain = TRealDomain() and realKind = 50 and extended = true +} + +/** + * The C/C++ floating point types. See 4.5. This includes `float`, `double` and `long double`, the + * fixed-size floating-point types like `_Float32`, the extended-precision floating-point types like + * `_Float64x`, and the decimal floating-point types like `_Decimal32`. It also includes the complex + * and imaginary versions of all of these types. */ class FloatingPointType extends ArithmeticType { + final int base; + final TypeDomain domain; + final int realKind; + final boolean extended; + FloatingPointType() { exists(int kind | builtintypes(underlyingElement(this), _, kind, _, _, _) and - ( - kind >= 24 and kind <= 32 - or - kind >= 38 and kind <= 42 - or - kind >= 45 and kind <= 50 - ) + floatingPointTypeMapping(kind, base, domain, realKind, extended) ) } + + /** Gets the numeric base of this type's representation: 2 (binary) or 10 (decimal). */ + final int getBase() { result = base } + + /** + * Gets the type domain of this type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + */ + final TypeDomain getDomain() { result = domain } + + /** + * Gets the corresponding real type of this type. For example, the corresponding real type of + * `_Complex double` is `double`. + */ + final RealNumberType getRealType() { + builtintypes(unresolveElement(result), _, realKind, _, _, _) + } + + /** Holds if this type is an extended precision floating-point type, such as `_Float32x`. */ + final predicate isExtendedPrecision() { extended = true } +} + +/** + * A floating-point type representing a real number. + */ +class RealNumberType extends FloatingPointType { + RealNumberType() { domain instanceof RealDomain } +} + +/** + * A floating-point type representing a complex number. + */ +class ComplexNumberType extends FloatingPointType { + ComplexNumberType() { domain instanceof ComplexDomain } +} + +/** + * A floating-point type representing an imaginary number. + */ +class ImaginaryNumberType extends FloatingPointType { + ImaginaryNumberType() { domain instanceof ImaginaryDomain } +} + +/** + * A floating-point type whose representation is base 2. + */ +class BinaryFloatingPointType extends FloatingPointType { + BinaryFloatingPointType() { base = 2 } +} + +/** + * A floating-point type whose representation is base 10. + */ +class DecimalFloatingPointType extends FloatingPointType { + DecimalFloatingPointType() { base = 10 } } /** @@ -727,7 +886,7 @@ class FloatingPointType extends ArithmeticType { * float f; * ``` */ -class FloatType extends FloatingPointType { +class FloatType extends RealNumberType, BinaryFloatingPointType { FloatType() { builtintypes(underlyingElement(this), _, 24, _, _, _) } override string getCanonicalQLClass() { result = "FloatType" } @@ -739,7 +898,7 @@ class FloatType extends FloatingPointType { * double d; * ``` */ -class DoubleType extends FloatingPointType { +class DoubleType extends RealNumberType, BinaryFloatingPointType { DoubleType() { builtintypes(underlyingElement(this), _, 25, _, _, _) } override string getCanonicalQLClass() { result = "DoubleType" } @@ -751,7 +910,7 @@ class DoubleType extends FloatingPointType { * long double ld; * ``` */ -class LongDoubleType extends FloatingPointType { +class LongDoubleType extends RealNumberType, BinaryFloatingPointType { LongDoubleType() { builtintypes(underlyingElement(this), _, 26, _, _, _) } override string getCanonicalQLClass() { result = "LongDoubleType" } @@ -763,7 +922,7 @@ class LongDoubleType extends FloatingPointType { * __float128 f128; * ``` */ -class Float128Type extends FloatingPointType { +class Float128Type extends RealNumberType, BinaryFloatingPointType { Float128Type() { builtintypes(underlyingElement(this), _, 38, _, _, _) } override string getCanonicalQLClass() { result = "Float128Type" } @@ -775,7 +934,7 @@ class Float128Type extends FloatingPointType { * _Decimal32 d32; * ``` */ -class Decimal32Type extends FloatingPointType { +class Decimal32Type extends RealNumberType, DecimalFloatingPointType { Decimal32Type() { builtintypes(underlyingElement(this), _, 40, _, _, _) } override string getCanonicalQLClass() { result = "Decimal32Type" } @@ -787,7 +946,7 @@ class Decimal32Type extends FloatingPointType { * _Decimal64 d64; * ``` */ -class Decimal64Type extends FloatingPointType { +class Decimal64Type extends RealNumberType, DecimalFloatingPointType { Decimal64Type() { builtintypes(underlyingElement(this), _, 41, _, _, _) } override string getCanonicalQLClass() { result = "Decimal64Type" } @@ -799,7 +958,7 @@ class Decimal64Type extends FloatingPointType { * _Decimal128 d128; * ``` */ -class Decimal128Type extends FloatingPointType { +class Decimal128Type extends RealNumberType, DecimalFloatingPointType { Decimal128Type() { builtintypes(underlyingElement(this), _, 42, _, _, _) } override string getCanonicalQLClass() { result = "Decimal128Type" } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 833c929ecc5..f843a6414e5 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -12,7 +12,9 @@ private newtype TIRType = TIRBooleanType(int byteSize) { Language::hasBooleanType(byteSize) } or TIRSignedIntegerType(int byteSize) { Language::hasSignedIntegerType(byteSize) } or TIRUnsignedIntegerType(int byteSize) { Language::hasUnsignedIntegerType(byteSize) } or - TIRFloatingPointType(int byteSize) { Language::hasFloatingPointType(byteSize) } or + TIRFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + Language::hasFloatingPointType(byteSize, base, domain) + } or TIRAddressType(int byteSize) { Language::hasAddressType(byteSize) } or TIRFunctionAddressType(int byteSize) { Language::hasFunctionAddressType(byteSize) } or TIROpaqueType(Language::OpaqueTypeTag tag, int byteSize) { @@ -104,7 +106,7 @@ private class IRSizedType extends IRType { this = TIRBooleanType(byteSize) or this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) or + this = TIRFloatingPointType(byteSize, _, _) or this = TIRAddressType(byteSize) or this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) @@ -133,7 +135,7 @@ class IRNumericType extends IRSizedType { IRNumericType() { this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) + this = TIRFloatingPointType(byteSize, _, _) } } @@ -171,14 +173,45 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { * A floating-point type. */ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { - final override string toString() { result = "float" + byteSize.toString() } + private final int base; + private final Language::TypeDomain domain; + + IRFloatingPointType() { + this = TIRFloatingPointType(_, base, domain) + } + + final override string toString() { + result = getDomainPrefix() + getBaseString() + byteSize.toString() + } final override Language::LanguageType getCanonicalLanguageType() { - result = Language::getCanonicalFloatingPointType(byteSize) + result = Language::getCanonicalFloatingPointType(byteSize, base, domain) } pragma[noinline] final override int getByteSize() { result = byteSize } + + /** Gets the numeric base of the type. Can be either 2 (binary) or 10 (decimal). */ + final int getBase() { result = base } + + /** + * Gets the type domain of the type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + */ + final Language::TypeDomain getDomain() { result = domain } + + private string getBaseString() { + base = 2 and result = "float" + or + base = 10 and result = "decimal" + } + + private string getDomainPrefix() { + domain instanceof Language::RealDomain and result = "" + or + domain instanceof Language::ComplexDomain and result = "c" + or + domain instanceof Language::ImaginaryDomain and result = "i" + } } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll index 9e8044ede4f..42420f8f925 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll @@ -86,9 +86,15 @@ predicate hasUnsignedIntegerType(int byteSize) { } /** - * Holds if an `IRFloatingPointType` with the specified `byteSize` should exist. + * Holds if an `IRFloatingPointType` with the specified size, base, and type domain should exist. */ -predicate hasFloatingPointType(int byteSize) { byteSize = any(FloatingPointType type).getSize() } +predicate hasFloatingPointType(int byteSize, int base, TypeDomain domain) { + exists(FloatingPointType type | + byteSize = type.getSize() and + base = type.getBase() and + domain = type.getDomain() + ) +} private predicate isPointerIshType(Type type) { type instanceof PointerType @@ -159,8 +165,13 @@ private IRType getIRTypeForPRValue(Type type) { isUnsignedIntegerType(unspecifiedType) and result.(IRUnsignedIntegerType).getByteSize() = type.getSize() or - unspecifiedType instanceof FloatingPointType and - result.(IRFloatingPointType).getByteSize() = type.getSize() + exists(FloatingPointType floatType, IRFloatingPointType irFloatType | + floatType = unspecifiedType and + irFloatType = result and + irFloatType.getByteSize() = floatType.getSize() and + irFloatType.getBase() = floatType.getBase() and + irFloatType.getDomain() = floatType.getDomain() + ) or isPointerIshType(unspecifiedType) and result.(IRAddressType).getByteSize() = getTypeSize(type) or @@ -438,15 +449,30 @@ CppPRValueType getCanonicalUnsignedIntegerType(int byteSize) { } /** - * Gets the `CppType` that is the canonical type for an `IRFloatingPointType` with the specified - * `byteSize`. + * Gets the sort priority of a `RealNumberType` base on its precision. */ -CppPRValueType getCanonicalFloatingPointType(int byteSize) { +private int getPrecisionPriority(RealNumberType type) { + // Prefer `double`, `float`, `long double` in that order. + if type instanceof DoubleType then result = 4 + else if type instanceof FloatType then result = 3 + else if type instanceof LongDoubleType then result = 2 + // If we get this far, prefer non-extended-precision types. + else if not type.isExtendedPrecision() then result = 1 + else result = 0 +} + +/** + * Gets the `CppType` that is the canonical type for an `IRFloatingPointType` with the specified + * size, base, and type domain. + */ +CppPRValueType getCanonicalFloatingPointType(int byteSize, int base, TypeDomain domain) { result = TPRValueType(max(FloatingPointType type | - type.getSize() = byteSize + type.getSize() = byteSize and + type.getBase() = base and + type.getDomain() = domain | - type order by type.toString() desc + type order by getPrecisionPriority(type.getRealType()), type.toString() desc )) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll index 6e88e711711..9268af428eb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -9,6 +9,11 @@ class LanguageType = CppType; class OpaqueTypeTag = Cpp::Type; +class TypeDomain = Cpp::TypeDomain; +class RealDomain = Cpp::RealDomain; +class ComplexDomain = Cpp::ComplexDomain; +class ImaginaryDomain = Cpp::ImaginaryDomain; + class Function = Cpp::Function; class Location = Cpp::Location; diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index abce5a6a19d..c01e93122a7 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -234,6 +234,62 @@ clang.cpp: # 6| 0: [VariableAccess] globalInt # 6| Type = [IntType] int # 6| ValueCategory = lvalue +complex.c: +# 1| [TopLevelFunction] void complex_math() +# 1| params: +# 1| body: [Block] { ... } +# 2| 0: [DeclStmt] declaration +# 2| 0: [VariableDeclarationEntry] definition of cf +# 2| Type = [ArithmeticType] _Complex float +# 2| init: [Initializer] initializer for cf +# 2| expr: [CStyleCast] (_Complex float)... +# 2| Conversion = [FloatingPointConversion] floating point conversion +# 2| Type = [ArithmeticType] _Complex float +# 2| ValueCategory = prvalue +# 2| expr: [AddExpr] ... + ... +# 2| Type = [ArithmeticType] _Complex double +# 2| ValueCategory = prvalue +# 2| 0: [CStyleCast] (_Complex double)... +# 2| Conversion = [FloatingPointConversion] floating point conversion +# 2| Type = [ArithmeticType] _Complex double +# 2| ValueCategory = prvalue +# 2| expr: [Literal] 2.0 +# 2| Type = [DoubleType] double +# 2| Value = [Literal] 2.0 +# 2| ValueCategory = prvalue +# 2| 1: [CStyleCast] (_Complex double)... +# 2| Conversion = [FloatingPointConversion] floating point conversion +# 2| Type = [ArithmeticType] _Complex double +# 2| ValueCategory = prvalue +# 2| expr: [Literal] (0.0,1.0i) +# 2| Type = [ArithmeticType] _Complex float +# 2| Value = [Literal] (0.0,1.0i) +# 2| ValueCategory = prvalue +# 3| 1: [DeclStmt] declaration +# 3| 0: [VariableDeclarationEntry] definition of cf2 +# 3| Type = [ArithmeticType] _Complex float +# 3| init: [Initializer] initializer for cf2 +# 3| expr: [MulExpr] ... * ... +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = prvalue +# 3| 0: [VariableAccess] cf +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = prvalue(load) +# 3| 1: [VariableAccess] cf +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = prvalue(load) +# 4| 2: [DeclStmt] declaration +# 4| 0: [VariableDeclarationEntry] definition of d +# 4| Type = [DoubleType] double +# 4| init: [Initializer] initializer for d +# 4| expr: [CStyleCast] (double)... +# 4| Conversion = [FloatingPointConversion] floating point conversion +# 4| Type = [DoubleType] double +# 4| ValueCategory = prvalue +# 4| expr: [VariableAccess] cf2 +# 4| Type = [ArithmeticType] _Complex float +# 4| ValueCategory = prvalue(load) +# 5| 3: [ReturnStmt] return ... ir.cpp: # 1| [TopLevelFunction] void Constants() # 1| params: diff --git a/cpp/ql/test/library-tests/ir/ir/complex.c b/cpp/ql/test/library-tests/ir/ir/complex.c new file mode 100644 index 00000000000..51775832586 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/complex.c @@ -0,0 +1,5 @@ +void complex_math(void) { + _Complex float cf = 2.0 + 1.0if; + _Complex float cf2 = cf * cf; + double d = cf2; +} diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index e4bbac446ba..f5e5b0b250d 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -124,6 +124,39 @@ clang.cpp: # 5| v5_8(void) = AliasedUse : ~mu5_4 # 5| v5_9(void) = ExitFunction : +complex.c: +# 1| void complex_math() +# 1| Block 0 +# 1| v1_1(void) = EnterFunction : +# 1| mu1_2(unknown) = AliasedDefinition : +# 1| mu1_3(unknown) = InitializeNonLocal : +# 1| mu1_4(unknown) = UnmodeledDefinition : +# 2| r2_1(glval<_Complex float>) = VariableAddress[cf] : +# 2| r2_2(double) = Constant[2.0] : +# 2| r2_3(_Complex double) = Convert : r2_2 +# 2| r2_4(_Complex float) = Constant[(0.0,1.0i)] : +# 2| r2_5(_Complex double) = Convert : r2_4 +# 2| r2_6(_Complex double) = Add : r2_3, r2_5 +# 2| r2_7(_Complex float) = Convert : r2_6 +# 2| mu2_8(_Complex float) = Store : &:r2_1, r2_7 +# 3| r3_1(glval<_Complex float>) = VariableAddress[cf2] : +# 3| r3_2(glval<_Complex float>) = VariableAddress[cf] : +# 3| r3_3(_Complex float) = Load : &:r3_2, ~mu1_4 +# 3| r3_4(glval<_Complex float>) = VariableAddress[cf] : +# 3| r3_5(_Complex float) = Load : &:r3_4, ~mu1_4 +# 3| r3_6(_Complex float) = Mul : r3_3, r3_5 +# 3| mu3_7(_Complex float) = Store : &:r3_1, r3_6 +# 4| r4_1(glval) = VariableAddress[d] : +# 4| r4_2(glval<_Complex float>) = VariableAddress[cf2] : +# 4| r4_3(_Complex float) = Load : &:r4_2, ~mu1_4 +# 4| r4_4(double) = Convert : r4_3 +# 4| mu4_5(double) = Store : &:r4_1, r4_4 +# 5| v5_1(void) = NoOp : +# 1| v1_5(void) = ReturnVoid : +# 1| v1_6(void) = UnmodeledUse : mu* +# 1| v1_7(void) = AliasedUse : ~mu1_4 +# 1| v1_8(void) = ExitFunction : + ir.cpp: # 1| void Constants() # 1| Block 0 diff --git a/cpp/ql/test/library-tests/ir/types/complex.c b/cpp/ql/test/library-tests/ir/types/complex.c new file mode 100644 index 00000000000..3766bde086a --- /dev/null +++ b/cpp/ql/test/library-tests/ir/types/complex.c @@ -0,0 +1,6 @@ +void Complex(void) { + _Complex float cf; //$irtype=cfloat8 + _Complex double cd; //$irtype=cfloat16 + _Complex long double cld; //$irtype=cfloat32 + // _Complex __float128 cf128; +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/types/irtypes.cpp b/cpp/ql/test/library-tests/ir/types/irtypes.cpp new file mode 100644 index 00000000000..321382567b7 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/types/irtypes.cpp @@ -0,0 +1,65 @@ +struct A { + int f_a; +}; + +struct B { + double f_a; + float f_b; +}; + +enum E { + Zero, + One, + Two, + Three +}; + +enum class ScopedE { + Zero, + One, + Two, + Three +}; + +void IRTypes() { + char c; //$irtype=int1 + signed char sc; //$irtype=int1 + unsigned char uc; //$irtype=uint1 + short s; //$irtype=int2 + signed short ss; //$irtype=int2 + unsigned short us; //$irtype=uint2 + int i; //$irtype=int4 + signed int si; //$irtype=int4 + unsigned int ui; //$irtype=uint4 + long l; //$irtype=int8 + signed long sl; //$irtype=int8 + unsigned long ul; //$irtype=uint8 + long long ll; //$irtype=int8 + signed long long sll; //$irtype=int8 + unsigned long long ull; //$irtype=uint8 + bool b; //$irtype=bool1 + float f; //$irtype=float4 + double d; //$irtype=float8 + long double ld; //$irtype=float16 + __float128 f128; //$irtype=float16 + + wchar_t wc; //$irtype=uint4 +// char8_t c8; //$irtype=uint1 + char16_t c16; //$irtype=uint2 + char32_t c32; //$irtype=uint4 + + int* pi; //$irtype=addr8 + int& ri = i; //$irtype=addr8 + void (*pfn)() = nullptr; //$irtype=func8 + void (&rfn)() = IRTypes; //$irtype=func8 + + A s_a; //$irtype=opaque4{A} + B s_b; //$irtype=opaque16{B} + + E e; //$irtype=uint4 + ScopedE se; //$irtype=uint4 + + B a_b[10]; //$irtype=opaque160{B[10]} +} + +// semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/types/irtypes.expected b/cpp/ql/test/library-tests/ir/types/irtypes.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cpp/ql/test/library-tests/ir/types/irtypes.ql b/cpp/ql/test/library-tests/ir/types/irtypes.ql new file mode 100644 index 00000000000..ef103e40c5b --- /dev/null +++ b/cpp/ql/test/library-tests/ir/types/irtypes.ql @@ -0,0 +1,18 @@ +private import cpp +private import semmle.code.cpp.ir.implementation.raw.IR +import TestUtilities.InlineExpectationsTest + +class IRTypesTest extends InlineExpectationsTest { + IRTypesTest() { this = "IRTypesTest" } + + override string getARelevantTag() { result = "irtype" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(IRUserVariable irVar | + location = irVar.getLocation() and + element = irVar.toString() and + tag = "irtype" and + value = irVar.getIRType().toString() + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index 833c929ecc5..f843a6414e5 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -12,7 +12,9 @@ private newtype TIRType = TIRBooleanType(int byteSize) { Language::hasBooleanType(byteSize) } or TIRSignedIntegerType(int byteSize) { Language::hasSignedIntegerType(byteSize) } or TIRUnsignedIntegerType(int byteSize) { Language::hasUnsignedIntegerType(byteSize) } or - TIRFloatingPointType(int byteSize) { Language::hasFloatingPointType(byteSize) } or + TIRFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + Language::hasFloatingPointType(byteSize, base, domain) + } or TIRAddressType(int byteSize) { Language::hasAddressType(byteSize) } or TIRFunctionAddressType(int byteSize) { Language::hasFunctionAddressType(byteSize) } or TIROpaqueType(Language::OpaqueTypeTag tag, int byteSize) { @@ -104,7 +106,7 @@ private class IRSizedType extends IRType { this = TIRBooleanType(byteSize) or this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) or + this = TIRFloatingPointType(byteSize, _, _) or this = TIRAddressType(byteSize) or this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) @@ -133,7 +135,7 @@ class IRNumericType extends IRSizedType { IRNumericType() { this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) + this = TIRFloatingPointType(byteSize, _, _) } } @@ -171,14 +173,45 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { * A floating-point type. */ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { - final override string toString() { result = "float" + byteSize.toString() } + private final int base; + private final Language::TypeDomain domain; + + IRFloatingPointType() { + this = TIRFloatingPointType(_, base, domain) + } + + final override string toString() { + result = getDomainPrefix() + getBaseString() + byteSize.toString() + } final override Language::LanguageType getCanonicalLanguageType() { - result = Language::getCanonicalFloatingPointType(byteSize) + result = Language::getCanonicalFloatingPointType(byteSize, base, domain) } pragma[noinline] final override int getByteSize() { result = byteSize } + + /** Gets the numeric base of the type. Can be either 2 (binary) or 10 (decimal). */ + final int getBase() { result = base } + + /** + * Gets the type domain of the type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + */ + final Language::TypeDomain getDomain() { result = domain } + + private string getBaseString() { + base = 2 and result = "float" + or + base = 10 and result = "decimal" + } + + private string getDomainPrefix() { + domain instanceof Language::RealDomain and result = "" + or + domain instanceof Language::ComplexDomain and result = "c" + or + domain instanceof Language::ImaginaryDomain and result = "i" + } } /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll index cffe3d09f39..fdd7ef804d2 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll @@ -61,9 +61,13 @@ predicate hasUnsignedIntegerType(int byteSize) { } /** - * Holds if an `IRFloatingPointType` with the specified `byteSize` should exist. + * Holds if an `IRFloatingPointType` with the specified size, base, and type domain should exist. */ -predicate hasFloatingPointType(int byteSize) { byteSize = any(FloatingPointType type).getSize() } +predicate hasFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + byteSize = any(FloatingPointType type).getSize() and + base = 2 and + domain instanceof Language::RealDomain +} private predicate isPointerIshType(Type type) { type instanceof PointerType or @@ -314,9 +318,11 @@ CSharpPRValueType getCanonicalUnsignedIntegerType(int byteSize) { /** * Gets the `CSharpType` that is the canonical type for an `IRFloatingPointType` with the specified - * `byteSize`. + * size, base, and type domain. */ -CSharpPRValueType getCanonicalFloatingPointType(int byteSize) { +CSharpPRValueType getCanonicalFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + base = 2 and + domain instanceof Language::RealDomain and result = TPRValueType(any(FloatingPointType type | type.getSize() = byteSize)) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll index a8fb448f8d0..24870f5635a 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll @@ -28,6 +28,43 @@ class IntegralType = CSharp::IntegralType; class FloatingPointType = CSharp::FloatingPointType; +private newtype TTypeDomain = TRealDomain() + +/** + * The type domain of a floating-point type. One of `RealDomain`, `ComplexDomain`, or + * `ImaginaryDomain`. + */ +class TypeDomain extends TTypeDomain { + string toString() { none() } +} + +/** + * The type domain of a floating-point type that represents a real number. + */ +class RealDomain extends TypeDomain, TRealDomain { + final override string toString() { result = "real" } +} + +/** + * The type domain of a floating-point type that represents a complex number. Not currently used in + * C#. + */ +class ComplexDomain extends TypeDomain { + ComplexDomain() { none() } + + final override string toString() { result = "complex" } +} + +/** + * The type domain of a floating-point type that represents an imaginary number. Not currently used + * in C#. + */ +class ImaginaryDomain extends TypeDomain { + ImaginaryDomain() { none() } + + final override string toString() { result = "imaginary" } +} + private newtype TClassDerivation = // Note that this is the `Class` type exported from this module, not CSharp::Class. MkClassDerivation(Class base, Class derived) { derived.getABaseType() = base } From 39dd9b709926e8906df5674a1abd5225e2a97150 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Fri, 27 Mar 2020 19:46:53 -0400 Subject: [PATCH 177/459] C++/C#: Fix formatting --- cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll | 8 +++----- cpp/ql/test/library-tests/ir/types/irtypes.ql | 2 +- .../src/semmle/code/csharp/ir/implementation/IRType.qll | 8 +++----- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index f843a6414e5..9a75ca19154 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -173,12 +173,10 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { * A floating-point type. */ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { - private final int base; - private final Language::TypeDomain domain; + final private int base; + final private Language::TypeDomain domain; - IRFloatingPointType() { - this = TIRFloatingPointType(_, base, domain) - } + IRFloatingPointType() { this = TIRFloatingPointType(_, base, domain) } final override string toString() { result = getDomainPrefix() + getBaseString() + byteSize.toString() diff --git a/cpp/ql/test/library-tests/ir/types/irtypes.ql b/cpp/ql/test/library-tests/ir/types/irtypes.ql index ef103e40c5b..56a7666458b 100644 --- a/cpp/ql/test/library-tests/ir/types/irtypes.ql +++ b/cpp/ql/test/library-tests/ir/types/irtypes.ql @@ -10,7 +10,7 @@ class IRTypesTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { exists(IRUserVariable irVar | location = irVar.getLocation() and - element = irVar.toString() and + element = irVar.toString() and tag = "irtype" and value = irVar.getIRType().toString() ) diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index f843a6414e5..9a75ca19154 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -173,12 +173,10 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { * A floating-point type. */ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { - private final int base; - private final Language::TypeDomain domain; + final private int base; + final private Language::TypeDomain domain; - IRFloatingPointType() { - this = TIRFloatingPointType(_, base, domain) - } + IRFloatingPointType() { this = TIRFloatingPointType(_, base, domain) } final override string toString() { result = getDomainPrefix() + getBaseString() + byteSize.toString() From 434e11c0c59b5d7cd17bb9e5be454a29b70f5e4e Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Fri, 27 Mar 2020 19:47:08 -0400 Subject: [PATCH 178/459] C++: Fix test output --- .../variables/variables/types.expected | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cpp/ql/test/library-tests/variables/variables/types.expected b/cpp/ql/test/library-tests/variables/variables/types.expected index cdc8c42a762..9f5df340263 100644 --- a/cpp/ql/test/library-tests/variables/variables/types.expected +++ b/cpp/ql/test/library-tests/variables/variables/types.expected @@ -1,21 +1,21 @@ | ..()(..) | RoutineType | | | | | | ..(*)(..) | FunctionPointerType | | ..()(..) | | | -| _Complex __float128 | FloatingPointType | | | | | -| _Complex double | FloatingPointType | | | | | -| _Complex float | FloatingPointType | | | | | -| _Complex long double | FloatingPointType | | | | | +| _Complex __float128 | BinaryFloatingPointType, ComplexNumberType | | | | | +| _Complex double | BinaryFloatingPointType, ComplexNumberType | | | | | +| _Complex float | BinaryFloatingPointType, ComplexNumberType | | | | | +| _Complex long double | BinaryFloatingPointType, ComplexNumberType | | | | | | _Decimal32 | Decimal32Type | | | | | | _Decimal64 | Decimal64Type | | | | | | _Decimal128 | Decimal128Type | | | | | -| _Float32 | FloatingPointType | | | | | -| _Float32x | FloatingPointType | | | | | -| _Float64 | FloatingPointType | | | | | -| _Float64x | FloatingPointType | | | | | -| _Float128 | FloatingPointType | | | | | -| _Float128x | FloatingPointType | | | | | -| _Imaginary double | FloatingPointType | | | | | -| _Imaginary float | FloatingPointType | | | | | -| _Imaginary long double | FloatingPointType | | | | | +| _Float32 | BinaryFloatingPointType, RealNumberType | | | | | +| _Float32x | BinaryFloatingPointType, RealNumberType | | | | | +| _Float64 | BinaryFloatingPointType, RealNumberType | | | | | +| _Float64x | BinaryFloatingPointType, RealNumberType | | | | | +| _Float128 | BinaryFloatingPointType, RealNumberType | | | | | +| _Float128x | BinaryFloatingPointType, RealNumberType | | | | | +| _Imaginary double | BinaryFloatingPointType, ImaginaryNumberType | | | | | +| _Imaginary float | BinaryFloatingPointType, ImaginaryNumberType | | | | | +| _Imaginary long double | BinaryFloatingPointType, ImaginaryNumberType | | | | | | __float128 | Float128Type | | | | | | __int128 | Int128Type | | | | | | __va_list_tag | DirectAccessHolder, MetricClass, Struct, StructLikeClass | | | | | From 7fce4ce9d1c9a34494ad82b6da6c7ae36434b5f1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Sat, 28 Mar 2020 12:34:05 +0100 Subject: [PATCH 179/459] Include join order fix from #3142 --- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll | 1 + cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll | 1 + cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll | 1 + cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll | 1 + .../src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll | 1 + cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll | 1 + .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 1 + .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 1 + .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 1 + .../ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll | 1 + .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll | 1 + .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll | 1 + .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll | 1 + .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll | 1 + java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll | 1 + java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll | 1 + java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll | 1 + java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll | 1 + java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll | 1 + 19 files changed, 19 insertions(+) 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 f7f9b2a0393..7d2d728b67e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 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 @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 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 @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 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 @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 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 @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { 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 f7f9b2a0393..7d2d728b67e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -548,6 +548,7 @@ private predicate throughFlowNodeCand(Node node, Configuration config) { } /** Holds if flow may return from `callable`. */ +pragma[nomagic] private predicate returnFlowCallableCand( DataFlowCallable callable, ReturnKindExt kind, Configuration config ) { From 0952064eb378accb48b68d86d04c518d1f1cc28d Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Sun, 29 Mar 2020 02:59:14 -0400 Subject: [PATCH 180/459] Move `sync-identical-files.py` into public repo as `sync-files.py` We currently use a script to keep certain duplicate QL files in sync across the repo. For historical reasons, this script has lived in the private repo alongside the rest of CodeQL, even though it's only used for files in the public `ql` repo. This PR moves the script into the public `ql` repo. It is still invoked by Jenkins scripts that live in the private repo during CI, but it can also be invoked directly without having a checkout of the private repo. This is useful for anyone who is modifying the dataflow or IR libraries with only a QL checkout. --- .gitignore | 3 + config/sync-files.py | 140 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 config/sync-files.py diff --git a/.gitignore b/.gitignore index 1768ebb161f..d020f307ebc 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ .vs/* !.vs/VSWorkspaceSettings.json +# Byte-compiled python files +*.pyc + # It's useful (though not required) to be able to unpack codeql in the ql checkout itself /codeql/ .vscode/settings.json diff --git a/config/sync-files.py b/config/sync-files.py new file mode 100644 index 00000000000..61faee83a8e --- /dev/null +++ b/config/sync-files.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +# Due to various technical limitations, we sometimes have files that need to be +# kept identical in the repository. This script loads a database of such +# files and can perform two functions: check whether they are still identical, +# and overwrite the others with a master copy if needed. + +import hashlib +import shutil +import os +import sys +import json +import re +from os import path + +file_groups = {} + +def add_prefix(prefix, relative): + result = path.join(prefix, relative) + if path.commonprefix((path.realpath(result), path.realpath(prefix))) != \ + path.realpath(prefix): + raise Exception("Path {} is not below {}".format( + result, prefix)) + return result + +def load_if_exists(prefix, json_file_relative): + json_file_name = path.join(prefix, json_file_relative) + if path.isfile(json_file_name): + print("Loading file groups from", json_file_name) + with open(json_file_name, 'r', encoding='utf-8') as fp: + raw_groups = json.load(fp) + prefixed_groups = { + name: [ + add_prefix(prefix, relative) + for relative in relatives + ] + for name, relatives in raw_groups.items() + } + file_groups.update(prefixed_groups) + +# Generates a list of C# test files that should be in sync +def csharp_test_files(): + test_file_re = re.compile('.*(Bad|Good)[0-9]*\\.cs$') + csharp_doc_files = { + file:os.path.join(root, file) + for root, dirs, files in os.walk("csharp/ql/src") + for file in files + if test_file_re.match(file) + } + return { + "C# test '" + file + "'" : [os.path.join(root, file), csharp_doc_files[file]] + for root, dirs, files in os.walk("csharp/ql/test") + for file in files + if file in csharp_doc_files + } + +def file_checksum(filename): + with open(filename, 'rb') as file_handle: + return hashlib.sha1(file_handle.read()).hexdigest() + +def check_group(group_name, files, master_file_picker, emit_error): + checksums = {file_checksum(f) for f in files} + + if len(checksums) == 1: + return + + master_file = master_file_picker(files) + if master_file is None: + emit_error(__file__, 0, + "Files from group '"+ group_name +"' not in sync.") + emit_error(__file__, 0, + "Run this script with a file-name argument among the " + "following to overwrite the remaining files with the contents " + "of that file or run with the --latest switch to update each " + "group of files from the most recently modified file in the group.") + for filename in files: + emit_error(__file__, 0, " " + filename) + else: + print(" Syncing others from", master_file) + for filename in files: + if filename == master_file: + continue + print(" " + filename) + os.replace(filename, filename + '~') + shutil.copy(master_file, filename) + print(" Backups written with '~' appended to file names") + +def chdir_repo_root(): + root_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..') + os.chdir(root_path) + +def choose_master_file(master_file, files): + if master_file in files: + return master_file + else: + return None + +def choose_latest_file(files): + latest_time = None + latest_file = None + for filename in files: + file_time = os.path.getmtime(filename) + if (latest_time is None) or (latest_time < file_time): + latest_time = file_time + latest_file = filename + return latest_file + +local_error_count = 0 +def emit_local_error(path, line, error): + print('ERROR: ' + path + ':' + line + " - " + error) + global local_error_count + local_error_count += 1 + +# This function is invoked directly by a CI script, which passes a different error-handling +# callback. +def sync_identical_files(emit_error): + if len(sys.argv) == 1: + master_file_picker = lambda files: None + elif len(sys.argv) == 2: + if sys.argv[1] == "--latest": + master_file_picker = lambda files: choose_latest_file(files) + elif os.path.isfile(sys.argv[1]): + master_file_picker = lambda files: choose_master_file(sys.argv[1], files) + else: + raise Exception("File not found") + else: + raise Exception("Bad command line or file not found") + chdir_repo_root() + load_if_exists('.', 'config/identical-files.json') + file_groups.update(csharp_test_files()) + for group_name, files in file_groups.items(): + check_group(group_name, files, master_file_picker, emit_error) + +def main(): + sync_identical_files(emit_local_error) + if local_error_count > 0: + exit(1) + +if __name__ == "__main__": + main() From 3eef2747d515c237127b04ca58c248c4f390c38b Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Sun, 29 Mar 2020 03:12:27 -0400 Subject: [PATCH 181/459] Fix LGTM alerts --- config/sync-files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/sync-files.py b/config/sync-files.py index 61faee83a8e..30be173c18b 100644 --- a/config/sync-files.py +++ b/config/sync-files.py @@ -11,7 +11,7 @@ import os import sys import json import re -from os import path +path = os.path file_groups = {} @@ -118,7 +118,7 @@ def sync_identical_files(emit_error): master_file_picker = lambda files: None elif len(sys.argv) == 2: if sys.argv[1] == "--latest": - master_file_picker = lambda files: choose_latest_file(files) + master_file_picker = choose_latest_file elif os.path.isfile(sys.argv[1]): master_file_picker = lambda files: choose_master_file(sys.argv[1], files) else: From 6b24e3c8be07368d82a2465217175e65b0d8c1e9 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Sun, 29 Mar 2020 08:18:05 -0400 Subject: [PATCH 182/459] C++: Fix formatting --- cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll index 9268af428eb..f047d6c4753 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -10,8 +10,11 @@ class LanguageType = CppType; class OpaqueTypeTag = Cpp::Type; class TypeDomain = Cpp::TypeDomain; + class RealDomain = Cpp::RealDomain; + class ComplexDomain = Cpp::ComplexDomain; + class ImaginaryDomain = Cpp::ImaginaryDomain; class Function = Cpp::Function; From e5e94e335756fbc781f111876d619758f055cb49 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Mon, 30 Mar 2020 10:35:47 +0100 Subject: [PATCH 183/459] Data flow: Add module doc comment for `TaintTrackingImpl.qll` Modelled after the correponding comment for `DataFlowImpl.qll`. --- .../internal/tainttracking1/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking2/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking1/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking2/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking1/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking2/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking3/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking4/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking5/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking1/TaintTrackingImpl.qll | 10 ++++++++++ .../internal/tainttracking2/TaintTrackingImpl.qll | 10 ++++++++++ 11 files changed, 110 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private From 0f0dc3c2aef49bc9815fd9e744fb806dea5ae109 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Mon, 30 Mar 2020 10:48:23 +0100 Subject: [PATCH 184/459] Update docs/language/learn-ql/python/ql-for-python.rst Co-Authored-By: Alistair <54933897+hubwriter@users.noreply.github.com> --- docs/language/learn-ql/python/ql-for-python.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/python/ql-for-python.rst b/docs/language/learn-ql/python/ql-for-python.rst index d43dc95dbd5..c9aa0a241e6 100644 --- a/docs/language/learn-ql/python/ql-for-python.rst +++ b/docs/language/learn-ql/python/ql-for-python.rst @@ -19,7 +19,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Functions in Python `: You can use syntactic classes from the standard CodeQL library to find Python functions and identify calls to them. -- :doc:`Expressions and statements in Python `: You can use syntactic classes from the CodeQL library to explore how Python expressions and statements are used in a code base. +- :doc:`Expressions and statements in Python `: You can use syntactic classes from the CodeQL library to explore how Python expressions and statements are used in a codebase. - :doc:`Analyzing control flow in Python `: You can write CodeQL queries to explore the control-flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. @@ -32,4 +32,4 @@ Further reading - For examples of how to query common Python elements, see the `JavaScript cookbook `__. - For the queries used in LGTM, display a `Python query `__ and click **Open in query console** to see the code used to find alerts. -- For more information about the library for JavaScript see the `CodeQL library for Python `__. \ No newline at end of file +- For more information about the library for JavaScript see the `CodeQL library for Python `__. From 87a9f51c78c083673d3906abffb3806f2634626a Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 30 Mar 2020 11:59:10 +0200 Subject: [PATCH 185/459] Python: Autoformat all `.ql` files. --- python/ql/examples/snippets/builtin_object.ql | 2 +- python/ql/examples/snippets/call.ql | 2 +- .../ql/examples/snippets/catch_exception.ql | 4 +- .../snippets/conditional_expression.ql | 7 +- python/ql/examples/snippets/emptyblock.ql | 2 +- python/ql/examples/snippets/emptythen.ql | 6 +- python/ql/examples/snippets/eq_true.ql | 2 +- python/ql/examples/snippets/equalitystmt.ql | 2 +- python/ql/examples/snippets/extend_class.ql | 4 +- python/ql/examples/snippets/filename.ql | 2 +- python/ql/examples/snippets/generator.ql | 2 +- .../ql/examples/snippets/integer_literal.ql | 2 +- python/ql/examples/snippets/method_call.ql | 4 +- python/ql/examples/snippets/new_instance.ql | 2 +- .../ql/examples/snippets/override_method.ql | 2 +- python/ql/examples/snippets/print.ql | 4 +- python/ql/examples/snippets/private_access.ql | 11 +- .../ql/examples/snippets/raise_exception.ql | 6 +- python/ql/examples/snippets/raw_string.ql | 4 +- python/ql/examples/snippets/store_none.ql | 4 +- python/ql/examples/snippets/tryfinally.ql | 5 +- .../ConflictingAttributesInBaseClasses.ql | 46 +-- .../DefineEqualsWhenAddingAttributes.ql | 25 +- python/ql/src/Classes/EqualsOrHash.ql | 31 +- python/ql/src/Classes/EqualsOrNotEquals.ql | 34 +-- python/ql/src/Classes/IncompleteOrdering.ql | 42 ++- python/ql/src/Classes/InconsistentMRO.ql | 11 +- .../ql/src/Classes/InitCallsSubclassMethod.ql | 33 +- .../Classes/MaybeUndefinedClassAttribute.ql | 21 +- python/ql/src/Classes/MissingCallToDel.ql | 8 +- python/ql/src/Classes/MissingCallToInit.ql | 6 +- python/ql/src/Classes/MutatingDescriptor.ql | 11 +- .../OverwritingAttributeInSuperClass.ql | 93 +++--- .../ql/src/Classes/PropertyInOldStyleClass.ql | 4 +- .../ql/src/Classes/ShouldBeContextManager.ql | 4 +- python/ql/src/Classes/SubclassShadowing.ql | 32 +- python/ql/src/Classes/SuperInOldStyleClass.ql | 11 +- .../SuperclassDelCalledMultipleTimes.ql | 23 +- .../SuperclassInitCalledMultipleTimes.ql | 23 +- .../ql/src/Classes/UndefinedClassAttribute.ql | 1 - python/ql/src/Classes/UselessClass.ql | 77 ++--- ...rongNameForArgumentInClassInstantiation.ql | 11 +- ...rongNumberArgumentsInClassInstantiation.ql | 18 +- .../src/Exceptions/CatchingBaseException.ql | 15 +- python/ql/src/Exceptions/EmptyExcept.ql | 44 ++- python/ql/src/Exceptions/IllegalRaise.ql | 10 +- .../NotImplementedIsNotAnException.ql | 1 - python/ql/src/Exceptions/RaisingTuple.ql | 13 +- .../Exceptions/UnguardedNextInGenerator.ql | 28 +- .../src/Expressions/CallToSuperWrongClass.ql | 18 +- python/ql/src/Expressions/CompareConstants.ql | 4 +- .../CompareIdenticalValuesMissingSelf.ql | 3 +- .../Comparisons/UselessComparisonTest.ql | 17 +- .../DuplicateKeyInDictionaryLiteral.ql | 25 +- .../ql/src/Expressions/ExplicitCallToDel.ql | 31 +- .../MixedExplicitImplicitIn3101Format.ql | 2 +- .../Formatting/UnusedArgumentIn3101Format.ql | 16 +- .../UnusedNamedArgumentIn3101Format.ql | 26 +- .../WrongNameInArgumentsFor3101Format.ql | 14 +- .../WrongNumberArgumentsFor3101Format.ql | 20 +- python/ql/src/Expressions/HashedButNoHash.ql | 27 +- .../Expressions/IncorrectComparisonUsingIs.ql | 15 +- .../ql/src/Expressions/NonCallableCalled.ql | 15 +- .../NonPortableComparisonUsingIs.ql | 16 +- .../src/Expressions/Regex/BackspaceEscape.ql | 11 +- .../Regex/DuplicateCharacterInSet.ql | 24 +- .../Regex/MissingPartSpecialGroup.ql | 2 - .../src/Expressions/Regex/UnmatchableCaret.ql | 7 +- .../Expressions/Regex/UnmatchableDollar.ql | 8 +- .../ql/src/Expressions/TruncatedDivision.ql | 51 ++-- ...nintentionalImplicitStringConcatenation.ql | 19 +- .../ql/src/Expressions/UnnecessaryLambda.ql | 60 ++-- .../Expressions/WrongNameForArgumentInCall.ql | 13 +- .../WrongNumberArgumentsForFormat.ql | 31 +- .../Expressions/WrongNumberArgumentsInCall.ql | 29 +- python/ql/src/Filters/ClassifyFiles.ql | 5 +- python/ql/src/Filters/NotGenerated.ql | 1 + python/ql/src/Filters/NotTest.ql | 1 + python/ql/src/Functions/ConsistentReturns.ql | 17 +- .../ql/src/Functions/DeprecatedSliceMethod.ql | 14 +- .../IncorrectRaiseInSpecialMethod.ql | 123 +++++--- .../Functions/IncorrectlyOverriddenMethod.ql | 24 +- .../IncorrectlySpecifiedOverriddenMethod.ql | 36 +-- python/ql/src/Functions/InitIsGenerator.ql | 5 +- python/ql/src/Functions/IterReturnsNonSelf.ql | 19 +- python/ql/src/Functions/NonCls.ql | 8 +- python/ql/src/Functions/NonSelf.ql | 6 +- .../src/Functions/OverlyComplexDelMethod.ql | 7 +- .../Functions/ReturnConsistentTupleSizes.ql | 7 +- python/ql/src/Functions/ReturnValueIgnored.ql | 62 ++-- .../Functions/SignatureOverriddenMethod.ql | 34 +-- .../src/Functions/SignatureSpecialMethods.ql | 286 +++++++++--------- .../Functions/UseImplicitNoneReturnValue.ql | 22 +- python/ql/src/Imports/DeprecatedModule.ql | 6 +- python/ql/src/Imports/EncodingError.ql | 2 +- .../ql/src/Imports/ImportShadowedByLoopVar.ql | 7 +- python/ql/src/Imports/ImportStarUsed.ql | 1 - python/ql/src/Imports/ImportandImportFrom.ql | 7 +- python/ql/src/Imports/Imports.ql | 13 +- python/ql/src/Imports/ModuleImportsItself.ql | 3 +- python/ql/src/Imports/MultipleImports.ql | 34 ++- python/ql/src/Imports/SyntaxError.ql | 2 +- python/ql/src/Imports/UnintentionalImport.ql | 6 +- python/ql/src/Lexical/CommentedOutCode.ql | 1 - python/ql/src/Lexical/FCommentedOutCode.ql | 4 +- python/ql/src/Lexical/OldOctalLiteral.ql | 3 +- python/ql/src/Metrics/CLinesOfCode.ql | 4 +- .../ql/src/Metrics/ClassAfferentCoupling.ql | 4 +- .../ql/src/Metrics/ClassEfferentCoupling.ql | 4 +- python/ql/src/Metrics/CommentRatio.ql | 5 +- python/ql/src/Metrics/CyclomaticComplexity.ql | 4 +- .../Dependencies/ExternalDependencies.ql | 28 +- .../ExternalDependenciesSourceLinks.ql | 11 +- python/ql/src/Metrics/DirectImports.ql | 1 + python/ql/src/Metrics/DocStringRatio.ql | 8 +- .../Metrics/External/CommitDisplayStrings.ql | 2 + .../src/Metrics/External/CommitSourceLinks.ql | 2 + python/ql/src/Metrics/FClasses.ql | 3 +- python/ql/src/Metrics/FFunctionsAndMethods.ql | 3 +- python/ql/src/Metrics/FLines.ql | 4 +- python/ql/src/Metrics/FLinesOfCode.ql | 4 +- python/ql/src/Metrics/FLinesOfComments.ql | 7 +- .../ql/src/Metrics/FLinesOfDuplicatedCode.ql | 22 +- python/ql/src/Metrics/FLinesOfSimilarCode.ql | 22 +- python/ql/src/Metrics/FNumberOfTests.ql | 5 +- .../ql/src/Metrics/FunctionNumberOfCalls.ql | 6 +- .../Metrics/FunctionStatementNestingDepth.ql | 4 +- python/ql/src/Metrics/History/HChurn.ql | 14 +- python/ql/src/Metrics/History/HLinesAdded.ql | 14 +- .../ql/src/Metrics/History/HLinesDeleted.ql | 14 +- .../src/Metrics/History/HNumberOfAuthors.ql | 2 +- .../src/Metrics/History/HNumberOfCoCommits.ql | 13 +- .../src/Metrics/History/HNumberOfCommits.ql | 1 + .../src/Metrics/History/HNumberOfReCommits.ql | 23 +- .../Metrics/History/HNumberOfRecentAuthors.ql | 12 +- .../History/HNumberOfRecentChangedFiles.ql | 11 +- .../Metrics/History/HNumberOfRecentCommits.ql | 2 +- .../Internal/CallableDisplayStrings.ql | 1 + .../src/Metrics/Internal/CallableExtents.ql | 1 + .../Metrics/Internal/CallableSourceLinks.ql | 1 + .../Metrics/Internal/ClassDisplayStrings.ql | 1 + .../ql/src/Metrics/Internal/ClassExtents.ql | 1 + .../src/Metrics/Internal/ClassSourceLinks.ql | 1 + .../src/Metrics/LackofCohesionInMethodsCK.ql | 6 +- .../src/Metrics/LackofCohesionInMethodsHM.ql | 6 +- .../ql/src/Metrics/ModuleAfferentCoupling.ql | 4 +- .../ql/src/Metrics/ModuleEfferentCoupling.ql | 4 +- .../NumberOfParametersWithoutDefault.ql | 4 +- python/ql/src/Metrics/NumberOfStatements.ql | 4 +- python/ql/src/Metrics/TransitiveImports.ql | 1 + python/ql/src/Numerics/Pythagorean.ql | 41 ++- .../CWE-020/IncompleteHostnameRegExp.ql | 3 +- .../Security/CWE-079/Jinja2WithoutEscaping.ql | 8 +- .../ql/src/Security/CWE-089/SqlInjection.ql | 4 +- .../CWE-295/MissingHostKeyValidation.ql | 6 +- .../src/Security/CWE-327/InsecureProtocol.ql | 4 +- .../Statements/IterableStringOrSequence.ql | 6 +- .../ql/src/Statements/ModificationOfLocals.ql | 4 +- .../ql/src/Statements/RedundantAssignment.ql | 9 +- python/ql/src/Testing/ImpreciseAssert.ql | 33 +- python/ql/src/analysis/AlertSuppression.ql | 65 ++-- python/ql/src/analysis/CallGraphEfficiency.ql | 32 +- .../analysis/CallGraphMarginalEfficiency.ql | 40 +-- python/ql/src/analysis/ContextEfficiency.ql | 33 +- .../src/analysis/ContextMarginalEfficiency.ql | 24 +- python/ql/src/analysis/Definitions.ql | 11 +- python/ql/src/analysis/Efficiency.ql | 31 +- python/ql/src/analysis/FailedInference.ql | 7 +- python/ql/src/analysis/ImportFailure.ql | 74 ++--- python/ql/src/analysis/KeyPointsToFailure.ql | 15 +- python/ql/src/analysis/PointsToFailure.ql | 8 +- python/ql/src/analysis/Pruned.ql | 9 +- python/ql/src/analysis/RatioOfDefinitions.ql | 17 +- python/ql/src/analysis/Sanity.ql | 214 ++++++++----- python/ql/src/analysis/Summary.ql | 67 ++-- .../ql/src/analysis/TypeHierarchyFailure.ql | 4 +- .../ql/src/analysis/TypeInferenceFailure.ql | 9 +- python/ql/src/external/DuplicateBlock.ql | 22 +- python/ql/src/external/DuplicateFunction.ql | 20 +- .../ql/src/external/MostlyDuplicateClass.ql | 9 +- python/ql/src/external/MostlyDuplicateFile.ql | 1 + python/ql/src/external/MostlySimilarFile.ql | 2 +- python/ql/src/external/SimilarFunction.ql | 15 +- .../ControlFlow/Exceptions/Handles.ql | 3 +- .../ControlFlow/Exceptions/Known.ql | 3 +- .../ControlFlow/Exceptions/Likely.ql | 8 +- .../ControlFlow/Exceptions/Unknown.ql | 3 +- .../PointsTo/import_time/Pruned.ql | 11 +- .../library-tests/PointsTo/imports/Runtime.ql | 11 +- .../library-tests/PointsTo/metaclass/test.ql | 1 - .../PointsTo/origin_uniqueness/Origin.ql | 15 +- .../library-tests/classes/attr/class_attr.ql | 10 +- .../classes/attr/class_has_attr.ql | 8 +- .../2/library-tests/classes/attr/list_attr.ql | 12 +- .../ql/test/2/library-tests/classes/mro/C3.ql | 8 +- .../test/2/library-tests/classes/mro/mro.ql | 7 +- .../comprehensions/SanityCheck.ql | 4 +- .../locations/general/AllLocations.ql | 7 +- .../locations/general/Locations.ql | 3 +- .../library-tests/locations/general/Prefix.ql | 5 +- .../locations/keywords/Locations.ql | 3 +- .../2/library-tests/locations/strings/test.ql | 2 +- .../modules/general/import_test.ql | 10 +- .../modules/general/moduleobject_test.ql | 1 - .../package_members/module_import_as.ql | 2 +- .../test/2/library-tests/objects/Literals.ql | 8 +- .../2/library-tests/types/classes/mro_test.ql | 2 - .../library-tests/types/classes/new_style.ql | 13 +- .../types/exceptions/ExitRaises.ql | 1 - .../library-tests/types/exceptions/Raises.ql | 9 +- .../2/library-tests/types/functions/Calls.ql | 1 - .../2/library-tests/types/functions/Never.ql | 2 +- .../types/functions/ReturnTypes.ql | 2 - .../types/properties/BuiltinProperties.ql | 9 +- .../ControlFlow/Exceptions/Handles.ql | 3 +- .../ControlFlow/Exceptions/Known.ql | 3 +- .../ControlFlow/Exceptions/Likely.ql | 8 +- .../ControlFlow/Exceptions/Unknown.ql | 3 +- .../library-tests/PointsTo/attributes/Test.ql | 2 - .../PointsTo/attributes/TestWithType.ql | 5 +- .../PointsTo/consts/BooleanConstants.ql | 15 +- .../PointsTo/import_time/Pruned.ql | 6 +- .../PointsTo/inheritance/Calls.ql | 3 - .../library-tests/PointsTo/metaclass/test.ql | 1 - .../subprocess-assert/ClassValue.ql | 5 +- .../PointsTo/typehints/Values.ql | 5 +- .../library-tests/classes/attr/class_attr.ql | 10 +- .../classes/attr/class_has_attr.ql | 8 +- .../test/3/library-tests/classes/meta/meta.ql | 2 +- .../3/library-tests/classes/meta/meta_obj.ql | 2 +- .../test/3/library-tests/classes/mro/mro.ql | 5 +- .../3/library-tests/classes/mro/mro_index.ql | 5 +- .../locations/annotations/Locations.ql | 3 +- .../locations/general/AllLocations.ql | 7 +- .../locations/general/Locations.ql | 3 +- .../library-tests/locations/general/Prefix.ql | 5 +- .../locations/keywords/Locations.ql | 3 +- .../modules/general/import_test.ql | 10 +- .../modules/general/moduleobject_test.ql | 1 - .../taint/unpacking/TestTaint.ql | 3 +- .../3/library-tests/types/classes/mro_test.ql | 2 - .../library-tests/types/exceptions/Raises.ql | 9 +- .../library-tests/types/exceptions/Viable.ql | 5 +- .../3/library-tests/types/functions/Calls.ql | 2 - .../3/library-tests/types/functions/Never.ql | 2 +- .../types/functions/ReturnTypes.ql | 2 - .../types/namespaces/NameSpace.ql | 28 +- .../types/properties/BuiltinProperties.ql | 9 +- .../PointsToSupport/UseFromDefinition.ql | 14 +- .../ControlFlow/augassign/AugAssignFlow.ql | 10 +- .../ControlFlow/augassign/Kind.ql | 19 +- .../ControlFlow/augassign/SSA.ql | 5 +- .../ControlFlow/comparison/Compare.ql | 13 +- .../library-tests/ControlFlow/delete/test.ql | 3 +- .../ControlFlow/dominators/DominatesSanity.ql | 13 +- .../ControlFlow/dominators/idom.ql | 7 +- .../ControlFlow/general/Comments.ql | 1 - .../ControlFlow/general/Cyclo.ql | 2 - .../general/ImmediateDominatorCheck.ql | 23 +- .../ControlFlow/general/Lines.ql | 7 +- .../ControlFlow/general/Reaches.ql | 5 +- .../ControlFlow/raising_stmts/RaisingFlow.ql | 16 +- .../ControlFlow/splitting/NodeCount.ql | 13 +- .../ControlFlow/splitting/SuccessorCount.ql | 11 +- .../ControlFlow/ssa/defns/test.ql | 4 +- .../ControlFlow/ssa/deletions/test.ql | 19 +- .../ssa/phi-nodes/phi_input_test.ql | 5 +- .../ControlFlow/ssa/phi-nodes/test.ql | 5 +- .../ControlFlow/ssa/undefined/test.ql | 4 +- .../ControlFlow/ssa/uses/test.ql | 4 +- .../ControlFlow/ssa/vars/test.ql | 5 +- .../ControlFlow/successors/Successors.ql | 25 +- .../truefalse/ExceptionalSuccessors.ql | 8 +- .../truefalse/TrueAndFalseSuccessor.ql | 4 +- .../truefalse/TrueFalseSuccessors.ql | 9 +- .../library-tests/ControlFlow/try/test_ssa.ql | 5 +- .../test/library-tests/DefUse/Definitions.ql | 2 +- python/ql/test/library-tests/DefUse/Uses.ql | 2 +- .../library-tests/DuplicateCode/Duplicate.ql | 16 +- .../DuplicateCode/DuplicateStatements.ql | 19 +- .../library-tests/DuplicateCode/Similar.ql | 13 +- .../library-tests/PointsTo/absent/Absent.ql | 2 - .../library-tests/PointsTo/api/ClassValue.ql | 3 +- .../library-tests/PointsTo/api/Constants.ql | 24 +- .../PointsTo/api/QualifedNames.ql | 25 +- .../test/library-tests/PointsTo/api/Value.ql | 13 +- .../library-tests/PointsTo/calls/Argument.ql | 2 +- .../test/library-tests/PointsTo/calls/Call.ql | 4 +- .../PointsTo/comparisons/PointsTo.ql | 1 - .../library-tests/PointsTo/customise/test.ql | 22 +- .../library-tests/PointsTo/decorators/Test.ql | 9 +- .../PointsTo/decorators/Values.ql | 5 +- .../PointsTo/extensions/Extend.ql | 26 +- .../library-tests/PointsTo/functions/Calls.ql | 15 +- .../PointsTo/functions/NeverReturns.ql | 1 - .../library-tests/PointsTo/functions/test.ql | 8 +- .../PointsTo/general/GlobalPointsTo.ql | 9 +- .../PointsTo/general/LocalPointsTo.ql | 6 +- .../PointsTo/general/LocalPointsToType.ql | 7 +- .../library-tests/PointsTo/global/Global.ql | 9 +- .../PointsTo/guarded/PointsTo.ql | 9 +- .../PointsTo/guarded/PointsToWithType.ql | 9 +- .../PointsTo/import_star/Values.ql | 4 +- .../library-tests/PointsTo/imports/Runtime.ql | 9 +- .../PointsTo/imports/RuntimeWithType.ql | 12 +- .../library-tests/PointsTo/indexing/Test.ql | 7 +- .../PointsTo/indexing/TestWithType.ql | 10 +- .../PointsTo/inheritance/BaseTypes.ql | 6 +- .../PointsTo/inheritance/Calls.ql | 3 - .../PointsTo/inheritance/Declared.ql | 1 - .../PointsTo/inheritance/Declares.ql | 1 - .../PointsTo/inheritance/Lookup.ql | 1 - .../PointsTo/inheritance/MetaClass.ql | 7 +- .../library-tests/PointsTo/inheritance/Mro.ql | 4 - .../PointsTo/inheritance/Self.ql | 1 - .../PointsTo/inheritance/SuperTypes.ql | 6 +- .../PointsTo/local/LocalPointsTo.ql | 7 +- .../library-tests/PointsTo/lookup/Lookup.ql | 17 +- .../PointsTo/metaclass/Failed.ql | 8 +- .../library-tests/PointsTo/metaclass/Mro.ql | 4 - .../library-tests/PointsTo/metaclass/Style.ql | 16 +- .../library-tests/PointsTo/metaclass/test.ql | 3 - .../test/library-tests/PointsTo/new/Call.ql | 4 +- .../library-tests/PointsTo/new/ClassMethod.ql | 5 +- .../library-tests/PointsTo/new/Dataflow.ql | 5 +- .../library-tests/PointsTo/new/Definitions.ql | 4 +- .../test/library-tests/PointsTo/new/Live.ql | 12 +- .../library-tests/PointsTo/new/NameSpace.ql | 28 +- .../library-tests/PointsTo/new/Parameters.ql | 6 +- .../PointsTo/new/PointsToMissing.ql | 5 +- .../PointsTo/new/PointsToNone.ql | 5 +- .../PointsTo/new/PointsToUnknown.ql | 2 - .../PointsTo/new/PointsToWithContext.ql | 5 +- .../PointsTo/new/PointsToWithType.ql | 5 +- .../library-tests/PointsTo/new/Precedes.ql | 5 +- .../library-tests/PointsTo/new/Reachable.ql | 1 - .../ql/test/library-tests/PointsTo/new/SSA.ql | 11 +- .../test/library-tests/PointsTo/new/Sanity.ql | 81 +++-- .../PointsTo/new/SourceEdgeDefinitions.ql | 2 - .../PointsTo/new/SourceNodeDefinitions.ql | 15 +- .../library-tests/PointsTo/new/SsaAttr.ql | 11 +- .../library-tests/PointsTo/new/SsaUses.ql | 1 - .../PointsTo/new/TestEvaluate.ql | 28 +- .../test/library-tests/PointsTo/new/Values.ql | 8 +- .../library-tests/PointsTo/new/VarUses.ql | 5 +- .../PointsTo/properties/Lookup.ql | 1 - .../PointsTo/properties/Values.ql | 4 +- .../library-tests/PointsTo/returns/Test.ql | 2 +- .../library-tests/PointsTo/subclass/Checks.ql | 3 +- .../PointsTo/subclass/TestEvaluate.ql | 12 +- .../library-tests/PointsTo/subclass/Values.ql | 3 - .../PointsTo/super/SuperMethodCall.ql | 9 +- .../library-tests/attributes/SelfAttribute.ql | 8 +- .../classes/abstract/Abstract.ql | 9 +- .../library-tests/classes/attr/class_attr.ql | 10 +- .../classes/attr/class_defined_attr.ql | 8 +- .../classes/attr/class_defines_attr.ql | 8 +- .../classes/attr/class_has_attr.ql | 8 +- .../test/library-tests/classes/attr/hash.ql | 13 +- .../ql/test/library-tests/classes/mro/C3.ql | 3 - .../ql/test/library-tests/comments/blocks.ql | 2 +- .../comments/blocks_not_example.ql | 3 +- .../ql/test/library-tests/comments/length.ql | 6 +- .../ql/test/library-tests/comments/lines.ql | 3 +- .../comments/lines_not_example.ql | 3 +- .../test/library-tests/comments/type_hint.ql | 2 - .../test/library-tests/comparisons/Compare.ql | 5 +- .../library-tests/comparisons/Compare2.ql | 13 +- .../comparisons/CompareControls.ql | 9 +- .../library-tests/comparisons/Implication.ql | 5 +- .../test/library-tests/comprehensions/Flow.ql | 2 +- .../dependencies/Dependencies.ql | 5 +- .../library-tests/descriptors/Descriptors.ql | 16 +- .../test/library-tests/descriptors/Methods.ql | 14 +- .../library-tests/encoding/CheckEncoding.ql | 6 +- .../test/library-tests/exceptions/Handles.ql | 2 +- .../ql/test/library-tests/exceptions/Legal.ql | 11 +- .../test/library-tests/exprs/ast/AstParent.ql | 6 +- .../ql/test/library-tests/exprs/ast/Child.ql | 1 - .../test/library-tests/exprs/compare/Test.ql | 2 - .../library-tests/exprs/strings/Strings.ql | 1 - .../library-tests/filters/generated/Filter.ql | 1 - .../library-tests/filters/tests/Filter.ql | 1 - .../formatting/FormatArguments.ql | 9 +- .../library-tests/formatting/FormatFields.ql | 1 - python/ql/test/library-tests/imports/Alias.ql | 2 +- .../test/library-tests/jump_to_defn/Remote.ql | 8 +- .../test/library-tests/jump_to_defn/Sanity.ql | 7 +- .../test/library-tests/jump_to_defn/Symbol.ql | 3 - .../test/library-tests/jump_to_defn/test.ql | 5 +- .../test/library-tests/locations/elif/test.ql | 2 +- .../implicit_concatenation/part_locations.ql | 11 +- .../locations/implicit_concatenation/parts.ql | 13 +- .../locations/implicit_concatenation/test.ql | 19 +- .../locations/negative_numbers/negative.ql | 16 +- .../locations/nested_classes/Test.ql | 2 - .../modules/duplicate_name/Modules.ql | 2 - .../modules/overlapping-paths/ModuleNames.ql | 1 - .../modules/spurious_init/ModuleNames.ql | 1 - .../ql/test/library-tests/objects/Literals.ql | 8 +- python/ql/test/library-tests/objects/Name.ql | 34 +-- .../ql/test/library-tests/objects/Strings.ql | 3 - .../library-tests/parameters/Annotations.ql | 2 - .../test/library-tests/parameters/Defaults.ql | 2 - .../test/library-tests/parameters/Special.ql | 13 +- .../test/library-tests/regex/Alternation.ql | 5 +- .../ql/test/library-tests/regex/Characters.ql | 3 - .../ql/test/library-tests/regex/FirstLast.ql | 4 +- .../test/library-tests/regex/GroupContents.ql | 5 +- python/ql/test/library-tests/regex/Mode.ql | 3 - .../ql/test/library-tests/regex/Qualified.ql | 2 - python/ql/test/library-tests/regex/Regex.ql | 4 +- .../ql/test/library-tests/scopes/Previous.ql | 2 +- .../security/sensitive/Sources.ql | 2 - .../test/library-tests/state_tracking/Test.ql | 14 +- .../state_tracking/Violations.ql | 15 +- .../library-tests/stmts/general/AstParent.ql | 7 +- .../stmts/general/SubExpressions.ql | 4 +- .../library-tests/stmts/raise_stmt/AST.ql | 5 +- .../test/library-tests/stmts/try_stmt/AST.ql | 5 +- .../test/library-tests/stmts/with_stmt/AST.ql | 5 +- .../taint/collections/TestTaint.ql | 3 +- .../taint/config/RockPaperScissors.ql | 4 +- .../test/library-tests/taint/config/Simple.ql | 4 +- .../taint/config/TaintedArgument.ql | 14 +- .../library-tests/taint/config/TestNode.ql | 5 +- .../library-tests/taint/config/TestSink.ql | 1 - .../library-tests/taint/config/TestSource.ql | 4 +- .../library-tests/taint/config/TestStep.ql | 9 +- .../library-tests/taint/dataflow/Dataflow.ql | 1 - .../library-tests/taint/dataflow/TestNode.ql | 3 +- .../test/library-tests/taint/example/Edges.ql | 21 +- .../taint/example/ExampleConfig.ql | 6 +- .../test/library-tests/taint/example/Nodes.ql | 5 +- .../taint/exception_traceback/TestNode.ql | 3 +- .../taint/exception_traceback/TestSource.ql | 8 +- .../taint/exception_traceback/TestStep.ql | 8 +- .../taint/extensions/TestNode.ql | 6 +- .../taint/extensions/TestStep.ql | 9 +- .../library-tests/taint/general/Contexts.ql | 7 +- .../taint/general/ModuleAttribute.ql | 2 - .../taint/general/ParamSource.ql | 28 +- .../taint/general/TaintSanity.ql | 39 +-- .../library-tests/taint/general/TestDefn.ql | 5 +- .../taint/general/TestSanitizers.ql | 3 - .../library-tests/taint/general/TestSink.ql | 4 +- .../library-tests/taint/general/TestSource.ql | 1 - .../library-tests/taint/general/TestStep.ql | 8 +- .../library-tests/taint/general/TestTaint.ql | 3 +- .../library-tests/taint/general/TestVar.ql | 5 +- .../taint/namedtuple/TestTaint.ql | 3 +- .../library-tests/taint/strings/TestStep.ql | 14 +- .../library-tests/taint/strings/TestTaint.ql | 3 +- .../taint/unpacking/TestTaint.ql | 3 +- python/ql/test/library-tests/thrift/Child.ql | 1 - python/ql/test/library-tests/thrift/File.ql | 5 +- .../ql/test/library-tests/thrift/Function.ql | 14 +- .../test/library-tests/thrift/References.ql | 1 - .../ql/test/library-tests/thrift/Service.ql | 2 - python/ql/test/library-tests/thrift/Test.ql | 2 - python/ql/test/library-tests/thrift/Value.ql | 3 +- .../library-tests/types/attributes/Test.ql | 4 +- .../types/classattr/ClassAttribute.ql | 17 +- .../types/classattr/ClassMember.ql | 16 +- .../types/classattr/SpecialAttribute.ql | 19 +- .../types/classes/FailedInference.ql | 7 +- .../types/classes/duplicate_base.ql | 2 - .../types/exceptions/ExitRaises.ql | 1 - .../library-tests/types/exceptions/Handles.ql | 2 - .../types/exceptions/Impossible.ql | 33 +- .../types/exceptions/LineRaises.ql | 7 +- .../library-tests/types/exceptions/Raises.ql | 9 +- .../types/exceptions/Reraises.ql | 4 +- .../library-tests/types/exceptions/Viable.ql | 5 +- .../library-tests/types/functions/Zope.ql | 1 - .../types/properties/Deleters.ql | 1 - .../library-tests/types/properties/Getters.ql | 1 - .../types/properties/PythonProperties.ql | 3 +- .../library-tests/types/properties/Setters.ql | 1 - .../variables/definitions/test.ql | 1 - .../library-tests/variables/scopes/free.ql | 7 +- .../library-tests/variables/scopes/globals.ql | 1 - .../library-tests/variables/scopes/locals.ql | 10 +- .../library-tests/variables/scopes/lookup.ql | 24 +- .../library-tests/variables/scopes/scopes.ql | 1 - .../web/client/requests/ClientHttpRequests.ql | 6 +- .../web/client/six/ClientHttpRequests.ql | 6 +- .../web/client/stdlib/ClientHttpRequests.ql | 6 +- .../query-tests/Metrics/ratios/CodeRatio.ql | 5 +- .../ql/test/query-tests/Resources/Dataflow.ql | 20 +- .../query-tests/Security/CWE-327/TestNode.ql | 1 - 491 files changed, 2649 insertions(+), 2747 deletions(-) diff --git a/python/ql/examples/snippets/builtin_object.ql b/python/ql/examples/snippets/builtin_object.ql index fd404aea563..7f552a5aa79 100644 --- a/python/ql/examples/snippets/builtin_object.ql +++ b/python/ql/examples/snippets/builtin_object.ql @@ -6,7 +6,7 @@ * builtin * object */ - + import python from Expr e, string name diff --git a/python/ql/examples/snippets/call.ql b/python/ql/examples/snippets/call.ql index d829802fd82..b326024a33c 100644 --- a/python/ql/examples/snippets/call.ql +++ b/python/ql/examples/snippets/call.ql @@ -5,7 +5,7 @@ * @tags call * function */ - + import python from Value len, CallNode call diff --git a/python/ql/examples/snippets/catch_exception.ql b/python/ql/examples/snippets/catch_exception.ql index e6f66a321c4..c117267d112 100644 --- a/python/ql/examples/snippets/catch_exception.ql +++ b/python/ql/examples/snippets/catch_exception.ql @@ -6,11 +6,11 @@ * try * exception */ - + import python from ExceptStmt ex, ClassValue cls -where +where cls.getName() = "MyExceptionClass" and ex.getType().pointsTo(cls) select ex diff --git a/python/ql/examples/snippets/conditional_expression.ql b/python/ql/examples/snippets/conditional_expression.ql index 3081d14757d..ee519aedb06 100644 --- a/python/ql/examples/snippets/conditional_expression.ql +++ b/python/ql/examples/snippets/conditional_expression.ql @@ -11,7 +11,8 @@ import python from IfExp e, ClassObject cls1, ClassObject cls2 -where - e.getBody().refersTo(_, cls1, _) and e.getOrelse().refersTo(_, cls2, _) and +where + e.getBody().refersTo(_, cls1, _) and + e.getOrelse().refersTo(_, cls2, _) and cls1 != cls2 -select e \ No newline at end of file +select e diff --git a/python/ql/examples/snippets/emptyblock.ql b/python/ql/examples/snippets/emptyblock.ql index 8f05150dc41..b45bb2f02c9 100644 --- a/python/ql/examples/snippets/emptyblock.ql +++ b/python/ql/examples/snippets/emptyblock.ql @@ -6,7 +6,7 @@ * block * statement */ - + import python from StmtList blk diff --git a/python/ql/examples/snippets/emptythen.ql b/python/ql/examples/snippets/emptythen.ql index 4c23c05ee71..bc017d4707a 100644 --- a/python/ql/examples/snippets/emptythen.ql +++ b/python/ql/examples/snippets/emptythen.ql @@ -1,7 +1,7 @@ /** * @id py/examples/emptythen * @name If statements with empty then branch - * @description Finds 'if' statements where the "then" branch + * @description Finds 'if' statements where the "then" branch * consists entirely of Pass statements * @tags if * then @@ -9,13 +9,13 @@ * conditional * branch */ - + import python from If i where not exists(Stmt s | - i.getStmt(_) = s and + i.getStmt(_) = s and not s instanceof Pass ) select i diff --git a/python/ql/examples/snippets/eq_true.ql b/python/ql/examples/snippets/eq_true.ql index 01c49d4d900..46091ea5474 100644 --- a/python/ql/examples/snippets/eq_true.ql +++ b/python/ql/examples/snippets/eq_true.ql @@ -6,7 +6,7 @@ * test * boolean */ - + import python from Compare eq diff --git a/python/ql/examples/snippets/equalitystmt.ql b/python/ql/examples/snippets/equalitystmt.ql index 674037ab2e6..60dd8880515 100644 --- a/python/ql/examples/snippets/equalitystmt.ql +++ b/python/ql/examples/snippets/equalitystmt.ql @@ -6,7 +6,7 @@ * equality * expression statement */ - + import python from ExprStmt e, Compare eq diff --git a/python/ql/examples/snippets/extend_class.ql b/python/ql/examples/snippets/extend_class.ql index 038fc78a9f2..cc4dd62647d 100644 --- a/python/ql/examples/snippets/extend_class.ql +++ b/python/ql/examples/snippets/extend_class.ql @@ -9,11 +9,11 @@ * subtype * supertype */ - + import python from ClassObject sub, ClassObject base -where +where base.getName() = "MyClass" and sub.getABaseType() = base select sub diff --git a/python/ql/examples/snippets/filename.ql b/python/ql/examples/snippets/filename.ql index eb8b9ccb7a2..579cceea47a 100644 --- a/python/ql/examples/snippets/filename.ql +++ b/python/ql/examples/snippets/filename.ql @@ -4,7 +4,7 @@ * @description Finds files called `spam.py` * @tags file */ - + import python from File f diff --git a/python/ql/examples/snippets/generator.ql b/python/ql/examples/snippets/generator.ql index c374895c8e6..573d8a2f757 100644 --- a/python/ql/examples/snippets/generator.ql +++ b/python/ql/examples/snippets/generator.ql @@ -10,4 +10,4 @@ import python from Function f where f.isGenerator() -select f \ No newline at end of file +select f diff --git a/python/ql/examples/snippets/integer_literal.ql b/python/ql/examples/snippets/integer_literal.ql index 1a1b4685ce8..debf88ca384 100644 --- a/python/ql/examples/snippets/integer_literal.ql +++ b/python/ql/examples/snippets/integer_literal.ql @@ -5,7 +5,7 @@ * @tags integer * literal */ - + import python from IntegerLiteral literal diff --git a/python/ql/examples/snippets/method_call.ql b/python/ql/examples/snippets/method_call.ql index c0b119c364c..9f78a4bb22f 100644 --- a/python/ql/examples/snippets/method_call.ql +++ b/python/ql/examples/snippets/method_call.ql @@ -5,11 +5,11 @@ * @tags call * method */ - + import python from AstNode call, PythonFunctionValue method -where +where method.getQualifiedName() = "MyClass.methodName" and method.getACall().getNode() = call select call diff --git a/python/ql/examples/snippets/new_instance.ql b/python/ql/examples/snippets/new_instance.ql index f6ede9fa8f6..c1293d6638c 100644 --- a/python/ql/examples/snippets/new_instance.ql +++ b/python/ql/examples/snippets/new_instance.ql @@ -6,7 +6,7 @@ * constructor * new */ - + import python from Call new, ClassValue cls diff --git a/python/ql/examples/snippets/override_method.ql b/python/ql/examples/snippets/override_method.ql index 81a02004e37..75c276df627 100644 --- a/python/ql/examples/snippets/override_method.ql +++ b/python/ql/examples/snippets/override_method.ql @@ -5,7 +5,7 @@ * @tags method * override */ - + import python from FunctionObject override, FunctionObject base diff --git a/python/ql/examples/snippets/print.ql b/python/ql/examples/snippets/print.ql index b48909fa108..1a560d48e3d 100644 --- a/python/ql/examples/snippets/print.ql +++ b/python/ql/examples/snippets/print.ql @@ -4,11 +4,11 @@ * @description Find print statements or calls to the builtin function 'print' * @tags print */ - + import python from AstNode print -where +where /* Python 2 without `from __future__ import print_function` */ print instanceof Print or diff --git a/python/ql/examples/snippets/private_access.ql b/python/ql/examples/snippets/private_access.ql index 5ea42e965d0..14548864579 100644 --- a/python/ql/examples/snippets/private_access.ql +++ b/python/ql/examples/snippets/private_access.ql @@ -1,19 +1,20 @@ /** * @id py/examples/private-access * @name Private access - * @description Find accesses to "private" attributes (those starting with an underscore) + * @description Find accesses to "private" attributes (those starting with an underscore) * @tags access * private */ - + import python predicate is_private(Attribute a) { - a.getName().matches("\\_%") and + a.getName().matches("\\_%") and not a.getName().matches("\\_\\_%\\_\\_") } from Attribute access -where is_private(access) and -not access.getObject().(Name).getId() = "self" +where + is_private(access) and + not access.getObject().(Name).getId() = "self" select access diff --git a/python/ql/examples/snippets/raise_exception.ql b/python/ql/examples/snippets/raise_exception.ql index 650af97ad6f..ce69c353780 100644 --- a/python/ql/examples/snippets/raise_exception.ql +++ b/python/ql/examples/snippets/raise_exception.ql @@ -6,13 +6,11 @@ * raise * exception */ - + import python from Raise raise, ClassValue ex where ex.getName() = "AnException" and - ( - raise.getException().pointsTo(ex.getASuperType()) - ) + raise.getException().pointsTo(ex.getASuperType()) select raise, "Don't raise instances of 'AnException'" diff --git a/python/ql/examples/snippets/raw_string.ql b/python/ql/examples/snippets/raw_string.ql index 3711d8d5171..78b1bbefb9a 100644 --- a/python/ql/examples/snippets/raw_string.ql +++ b/python/ql/examples/snippets/raw_string.ql @@ -1,11 +1,11 @@ /** * @id py/examples/raw-string * @name Raw string literals - * @description Finds string literals with an 'r' prefix + * @description Finds string literals with an 'r' prefix * @tags string * raw */ - + import python from StrConst s diff --git a/python/ql/examples/snippets/store_none.ql b/python/ql/examples/snippets/store_none.ql index dfcac497908..88aaac47f56 100644 --- a/python/ql/examples/snippets/store_none.ql +++ b/python/ql/examples/snippets/store_none.ql @@ -8,11 +8,11 @@ * collection * add */ - + import python from SubscriptNode store -where +where store.isStore() and store.getIndex().pointsTo(Value::named("None")) select store diff --git a/python/ql/examples/snippets/tryfinally.ql b/python/ql/examples/snippets/tryfinally.ql index f37b86f3fa6..bf5ea3c61a6 100644 --- a/python/ql/examples/snippets/tryfinally.ql +++ b/python/ql/examples/snippets/tryfinally.ql @@ -10,6 +10,7 @@ import python from Try t -where exists(t.getFinalbody()) - and not exists(t.getAHandler()) +where + exists(t.getFinalbody()) and + not exists(t.getAHandler()) select t diff --git a/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql b/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql index 44be7ac9157..b4829809135 100644 --- a/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql +++ b/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql @@ -15,13 +15,13 @@ import python predicate does_nothing(PyFunctionObject f) { not exists(Stmt s | s.getScope() = f.getFunction() | - not s instanceof Pass and not ((ExprStmt)s).getValue() = f.getFunction().getDocString() + not s instanceof Pass and not s.(ExprStmt).getValue() = f.getFunction().getDocString() ) } /* If a method performs a super() call then it is OK as the 'overridden' method will get called */ predicate calls_super(FunctionObject f) { - exists(Call sup, Call meth, Attribute attr, GlobalVariable v | + exists(Call sup, Call meth, Attribute attr, GlobalVariable v | meth.getScope() = f.getFunction() and meth.getFunc() = attr and attr.getObject() = sup and @@ -33,25 +33,29 @@ predicate calls_super(FunctionObject f) { /** Holds if the given name is white-listed for some reason */ predicate whitelisted(string name) { - /* The standard library specifically recommends this :( - * See https://docs.python.org/3/library/socketserver.html#asynchronous-mixins */ + /* + * The standard library specifically recommends this :( + * See https://docs.python.org/3/library/socketserver.html#asynchronous-mixins + */ + name = "process_request" } -from ClassObject c, ClassObject b1, ClassObject b2, string name, -int i1, int i2, Object o1, Object o2 -where c.getBaseType(i1) = b1 and -c.getBaseType(i2) = b2 and -i1 < i2 and o1 != o2 and -o1 = b1.lookupAttribute(name) and -o2 = b2.lookupAttribute(name) and -not name.matches("\\_\\_%\\_\\_") and -not calls_super(o1) and -not does_nothing(o2) and -not whitelisted(name) and -not o1.overrides(o2) and -not o2.overrides(o1) and -not c.declaresAttribute(name) - -select c, "Base classes have conflicting values for attribute '" + name + "': $@ and $@.", o1, o1.toString(), o2, o2.toString() - +from + ClassObject c, ClassObject b1, ClassObject b2, string name, int i1, int i2, Object o1, Object o2 +where + c.getBaseType(i1) = b1 and + c.getBaseType(i2) = b2 and + i1 < i2 and + o1 != o2 and + o1 = b1.lookupAttribute(name) and + o2 = b2.lookupAttribute(name) and + not name.matches("\\_\\_%\\_\\_") and + not calls_super(o1) and + not does_nothing(o2) and + not whitelisted(name) and + not o1.overrides(o2) and + not o2.overrides(o1) and + not c.declaresAttribute(name) +select c, "Base classes have conflicting values for attribute '" + name + "': $@ and $@.", o1, + o1.toString(), o2, o2.toString() diff --git a/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql b/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql index 5b80f2fd7bf..8bf7d24b729 100644 --- a/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql +++ b/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql @@ -15,7 +15,9 @@ import semmle.python.SelfAttribute import Equality predicate class_stores_to_attribute(ClassObject cls, SelfAttributeStore store, string name) { - exists(FunctionObject f | f = cls.declaredAttribute(_) and store.getScope() = f.getFunction() and store.getName() = name) and + exists(FunctionObject f | + f = cls.declaredAttribute(_) and store.getScope() = f.getFunction() and store.getName() = name + ) and /* Exclude classes used as metaclasses */ not cls.getASuperType() = theTypeType() } @@ -30,23 +32,26 @@ predicate should_override_eq(ClassObject cls, Object base_eq) { ) } -/** Does the non-overridden __eq__ method access the attribute, +/** + * Does the non-overridden __eq__ method access the attribute, * which implies that the __eq__ method does not need to be overridden. */ predicate superclassEqExpectsAttribute(ClassObject cls, PyFunctionObject base_eq, string attrname) { not cls.declaresAttribute("__eq__") and exists(ClassObject sup | sup = cls.getABaseType() and sup.declaredAttribute("__eq__") = base_eq | - exists(SelfAttributeRead store | - store.getName() = attrname | + exists(SelfAttributeRead store | store.getName() = attrname | store.getScope() = base_eq.getFunction() ) ) } from ClassObject cls, SelfAttributeStore store, Object base_eq -where class_stores_to_attribute(cls, store, _) and should_override_eq(cls, base_eq) and -/* Don't report overridden unittest.TestCase. -- TestCase overrides __eq__, but subclasses do not really need to. */ -not cls.getASuperType().getName() = "TestCase" and -not superclassEqExpectsAttribute(cls, base_eq, store.getName()) - -select cls, "The class '" + cls.getName() + "' does not override $@, but adds the new attribute $@.", base_eq, "'__eq__'", store, store.getName() +where + class_stores_to_attribute(cls, store, _) and + should_override_eq(cls, base_eq) and + /* Don't report overridden unittest.TestCase. -- TestCase overrides __eq__, but subclasses do not really need to. */ + not cls.getASuperType().getName() = "TestCase" and + not superclassEqExpectsAttribute(cls, base_eq, store.getName()) +select cls, + "The class '" + cls.getName() + "' does not override $@, but adds the new attribute $@.", base_eq, + "'__eq__'", store, store.getName() diff --git a/python/ql/src/Classes/EqualsOrHash.ql b/python/ql/src/Classes/EqualsOrHash.ql index c748675850c..795e7f4c0ff 100644 --- a/python/ql/src/Classes/EqualsOrHash.ql +++ b/python/ql/src/Classes/EqualsOrHash.ql @@ -14,8 +14,11 @@ import python CallableValue defines_equality(ClassValue c, string name) { - (name = "__eq__" or major_version() = 2 and name = "__cmp__") - and + ( + name = "__eq__" + or + major_version() = 2 and name = "__cmp__" + ) and result = c.declaredAttribute(name) } @@ -26,8 +29,12 @@ CallableValue implemented_method(ClassValue c, string name) { } string unimplemented_method(ClassValue c) { - not exists(defines_equality(c, _)) and - (result = "__eq__" and major_version() = 3 or major_version() = 2 and result = "__eq__ or __cmp__") + not exists(defines_equality(c, _)) and + ( + result = "__eq__" and major_version() = 3 + or + major_version() = 2 and result = "__eq__ or __cmp__" + ) or /* Python 3 automatically makes classes unhashable if __eq__ is defined, but __hash__ is not */ not c.declaresAttribute(result) and result = "__hash__" and major_version() = 2 @@ -41,13 +48,15 @@ predicate unhashable(ClassValue cls) { } predicate violates_hash_contract(ClassValue c, string present, string missing, Value method) { - not unhashable(c) and - missing = unimplemented_method(c) and - method = implemented_method(c, present) and - not c.failedInference(_) + not unhashable(c) and + missing = unimplemented_method(c) and + method = implemented_method(c, present) and + not c.failedInference(_) } from ClassValue c, string present, string missing, CallableValue method -where violates_hash_contract(c, present, missing, method) and -exists(c.getScope()) // Suppress results that aren't from source -select method, "Class $@ implements " + present + " but does not define " + missing + ".", c, c.getName() +where + violates_hash_contract(c, present, missing, method) and + exists(c.getScope()) // Suppress results that aren't from source +select method, "Class $@ implements " + present + " but does not define " + missing + ".", c, + c.getName() diff --git a/python/ql/src/Classes/EqualsOrNotEquals.ql b/python/ql/src/Classes/EqualsOrNotEquals.ql index 606718bac6b..7457de441b0 100644 --- a/python/ql/src/Classes/EqualsOrNotEquals.ql +++ b/python/ql/src/Classes/EqualsOrNotEquals.ql @@ -13,16 +13,12 @@ import python import Equality -string equals_or_ne() { - result = "__eq__" or result = "__ne__" -} +string equals_or_ne() { result = "__eq__" or result = "__ne__" } predicate total_ordering(Class cls) { - exists(Attribute a | a = cls.getADecorator() | - a.getName() = "total_ordering") + exists(Attribute a | a = cls.getADecorator() | a.getName() = "total_ordering") or - exists(Name n | n = cls.getADecorator() | - n.getId() = "total_ordering") + exists(Name n | n = cls.getADecorator() | n.getId() = "total_ordering") } CallableValue implemented_method(ClassValue c, string name) { @@ -33,18 +29,20 @@ string unimplemented_method(ClassValue c) { not c.declaresAttribute(result) and result = equals_or_ne() } -predicate violates_equality_contract(ClassValue c, string present, string missing, CallableValue method) { - missing = unimplemented_method(c) and - method = implemented_method(c, present) and - not c.failedInference(_) and - not total_ordering(c.getScope()) and - /* Python 3 automatically implements __ne__ if __eq__ is defined, but not vice-versa */ - not (major_version() = 3 and present = "__eq__" and missing = "__ne__") and - not method.getScope() instanceof DelegatingEqualityMethod and - not c.lookup(missing).(CallableValue).getScope() instanceof DelegatingEqualityMethod +predicate violates_equality_contract( + ClassValue c, string present, string missing, CallableValue method +) { + missing = unimplemented_method(c) and + method = implemented_method(c, present) and + not c.failedInference(_) and + not total_ordering(c.getScope()) and + /* Python 3 automatically implements __ne__ if __eq__ is defined, but not vice-versa */ + not (major_version() = 3 and present = "__eq__" and missing = "__ne__") and + not method.getScope() instanceof DelegatingEqualityMethod and + not c.lookup(missing).(CallableValue).getScope() instanceof DelegatingEqualityMethod } from ClassValue c, string present, string missing, CallableValue method where violates_equality_contract(c, present, missing, method) - -select method, "Class $@ implements " + present + " but does not implement " + missing + ".", c, c.getName() +select method, "Class $@ implements " + present + " but does not implement " + missing + ".", c, + c.getName() diff --git a/python/ql/src/Classes/IncompleteOrdering.ql b/python/ql/src/Classes/IncompleteOrdering.ql index 767e7ce6c37..7755696bd45 100644 --- a/python/ql/src/Classes/IncompleteOrdering.ql +++ b/python/ql/src/Classes/IncompleteOrdering.ql @@ -13,17 +13,18 @@ import python predicate total_ordering(Class cls) { - exists(Attribute a | a = cls.getADecorator() | - a.getName() = "total_ordering") + exists(Attribute a | a = cls.getADecorator() | a.getName() = "total_ordering") or - exists(Name n | n = cls.getADecorator() | - n.getId() = "total_ordering") + exists(Name n | n = cls.getADecorator() | n.getId() = "total_ordering") } string ordering_name(int n) { - result = "__lt__" and n = 1 or - result = "__le__" and n = 2 or - result = "__gt__" and n = 3 or + result = "__lt__" and n = 1 + or + result = "__le__" and n = 2 + or + result = "__gt__" and n = 3 + or result = "__ge__" and n = 4 } @@ -32,8 +33,7 @@ predicate overrides_ordering_method(ClassValue c, string name) { ( c.declaresAttribute(name) or - exists(ClassValue sup | - sup = c.getASuperType() and not sup = Value::named("object") | + exists(ClassValue sup | sup = c.getASuperType() and not sup = Value::named("object") | sup.declaresAttribute(name) ) ) @@ -41,15 +41,14 @@ predicate overrides_ordering_method(ClassValue c, string name) { string unimplemented_ordering(ClassValue c, int n) { not c = Value::named("object") and - not overrides_ordering_method(c, result) and + not overrides_ordering_method(c, result) and result = ordering_name(n) } string unimplemented_ordering_methods(ClassValue c, int n) { n = 0 and result = "" and exists(unimplemented_ordering(c, _)) or - exists(string prefix, int nm1 | - n = nm1 + 1 and prefix = unimplemented_ordering_methods(c, nm1) | + exists(string prefix, int nm1 | n = nm1 + 1 and prefix = unimplemented_ordering_methods(c, nm1) | prefix = "" and result = unimplemented_ordering(c, n) or result = prefix and not exists(unimplemented_ordering(c, n)) and n < 5 @@ -60,16 +59,15 @@ string unimplemented_ordering_methods(ClassValue c, int n) { Value ordering_method(ClassValue c, string name) { /* If class doesn't declare a method then don't blame this class (the superclass will be blamed). */ - name = ordering_name(_) and result = c.declaredAttribute(name) + name = ordering_name(_) and result = c.declaredAttribute(name) } from ClassValue c, Value ordering, string name -where not c.failedInference(_) and -not total_ordering(c.getScope()) -and ordering = ordering_method(c, name) and -exists(unimplemented_ordering(c, _)) - -select c, "Class " + c.getName() + " implements $@, but does not implement " + unimplemented_ordering_methods(c, 4) + ".", -ordering, name - - +where + not c.failedInference(_) and + not total_ordering(c.getScope()) and + ordering = ordering_method(c, name) and + exists(unimplemented_ordering(c, _)) +select c, + "Class " + c.getName() + " implements $@, but does not implement " + + unimplemented_ordering_methods(c, 4) + ".", ordering, name diff --git a/python/ql/src/Classes/InconsistentMRO.ql b/python/ql/src/Classes/InconsistentMRO.ql index 08b1016086c..a9541bc9023 100644 --- a/python/ql/src/Classes/InconsistentMRO.ql +++ b/python/ql/src/Classes/InconsistentMRO.ql @@ -13,15 +13,18 @@ import python ClassObject left_base(ClassObject type, ClassObject base) { - exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i-1)) + exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i - 1)) } predicate invalid_mro(ClassObject t, ClassObject left, ClassObject right) { t.isNewStyle() and - left = left_base(t, right) and left = right.getAnImproperSuperType() + left = left_base(t, right) and + left = right.getAnImproperSuperType() } from ClassObject t, ClassObject left, ClassObject right where invalid_mro(t, left, right) -select t, "Construction of class " + t.getName() + " can fail due to invalid method resolution order(MRO) for bases $@ and $@.", -left, left.getName(), right, right.getName() \ No newline at end of file +select t, + "Construction of class " + t.getName() + + " can fail due to invalid method resolution order(MRO) for bases $@ and $@.", left, + left.getName(), right, right.getName() diff --git a/python/ql/src/Classes/InitCallsSubclassMethod.ql b/python/ql/src/Classes/InitCallsSubclassMethod.ql index 5a191d861bf..b0e1cc0d8f0 100644 --- a/python/ql/src/Classes/InitCallsSubclassMethod.ql +++ b/python/ql/src/Classes/InitCallsSubclassMethod.ql @@ -13,23 +13,18 @@ import python - -from ClassObject supercls, string method, Call call, - FunctionObject overriding, FunctionObject overridden - +from + ClassObject supercls, string method, Call call, FunctionObject overriding, + FunctionObject overridden where -exists(FunctionObject init, SelfAttribute sa | - supercls.declaredAttribute("__init__") = init and - call.getScope() = init.getFunction() and call.getFunc() = sa | - sa.getName() = method and - overridden = supercls.declaredAttribute(method) and - overriding.overrides(overridden) -) - -select call, "Call to self.$@ in __init__ method, which is overridden by $@.", - overridden, method, - overriding, overriding.descriptiveString() - - - - + exists(FunctionObject init, SelfAttribute sa | + supercls.declaredAttribute("__init__") = init and + call.getScope() = init.getFunction() and + call.getFunc() = sa + | + sa.getName() = method and + overridden = supercls.declaredAttribute(method) and + overriding.overrides(overridden) + ) +select call, "Call to self.$@ in __init__ method, which is overridden by $@.", overridden, method, + overriding, overriding.descriptiveString() diff --git a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql index ec2e91987dd..ca8a260b863 100644 --- a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql +++ b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql @@ -16,26 +16,29 @@ import ClassAttributes predicate guarded_by_other_attribute(SelfAttributeRead a, CheckClass c) { c.sometimesDefines(a.getName()) and - exists(SelfAttributeRead guard, If i | + exists(SelfAttributeRead guard, If i | i.contains(a) and - c.assignedInInit(guard.getName()) | + c.assignedInInit(guard.getName()) + | i.getTest() = guard or i.getTest().contains(guard) ) } - predicate maybe_undefined_class_attribute(SelfAttributeRead a, CheckClass c) { c.sometimesDefines(a.getName()) and not c.alwaysDefines(a.getName()) and - c.interestingUndefined(a) and + c.interestingUndefined(a) and not guarded_by_other_attribute(a, c) } from Attribute a, ClassObject c, SelfAttributeStore sa -where maybe_undefined_class_attribute(a, c) and -sa.getClass() = c.getPyClass() and sa.getName() = a.getName() -select a, "Attribute '" + a.getName() + -"' is not defined in the class body nor in the __init__() method, but it is defined $@", sa, "here" - +where + maybe_undefined_class_attribute(a, c) and + sa.getClass() = c.getPyClass() and + sa.getName() = a.getName() +select a, + "Attribute '" + a.getName() + + "' is not defined in the class body nor in the __init__() method, but it is defined $@", sa, + "here" diff --git a/python/ql/src/Classes/MissingCallToDel.ql b/python/ql/src/Classes/MissingCallToDel.ql index d08c8399669..b54a9b8c782 100644 --- a/python/ql/src/Classes/MissingCallToDel.ql +++ b/python/ql/src/Classes/MissingCallToDel.ql @@ -13,14 +13,12 @@ import python import MethodCallOrder - from ClassObject self, FunctionObject missing - where missing_call_to_superclass_method(self, _, missing, "__del__") and not missing.neverReturns() and not self.failedInference() and not missing.isBuiltin() -select self, "Class " + self.getName() + " may not be cleaned up properly as $@ is not called during deletion.", -missing, missing.descriptiveString() - +select self, + "Class " + self.getName() + " may not be cleaned up properly as $@ is not called during deletion.", + missing, missing.descriptiveString() diff --git a/python/ql/src/Classes/MissingCallToInit.ql b/python/ql/src/Classes/MissingCallToInit.ql index ad137f817f4..bb6121e33b6 100644 --- a/python/ql/src/Classes/MissingCallToInit.ql +++ b/python/ql/src/Classes/MissingCallToInit.ql @@ -14,7 +14,6 @@ import python import MethodCallOrder from ClassObject self, FunctionObject initializer, FunctionObject missing - where self.lookupAttribute("__init__") = initializer and missing_call_to_superclass_method(self, initializer, missing, "__init__") and @@ -24,5 +23,6 @@ where not self.failedInference() and not missing.isBuiltin() and not self.isAbstract() -select self, "Class " + self.getName() + " may not be initialized properly as $@ is not called from its $@.", -missing, missing.descriptiveString(), initializer, "__init__ method" \ No newline at end of file +select self, + "Class " + self.getName() + " may not be initialized properly as $@ is not called from its $@.", + missing, missing.descriptiveString(), initializer, "__init__ method" diff --git a/python/ql/src/Classes/MutatingDescriptor.ql b/python/ql/src/Classes/MutatingDescriptor.ql index 65659526f57..1f1188c2830 100644 --- a/python/ql/src/Classes/MutatingDescriptor.ql +++ b/python/ql/src/Classes/MutatingDescriptor.ql @@ -15,8 +15,7 @@ import python predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) { cls.isDescriptorType() and exists(PyFunctionObject f, PyFunctionObject get_set | - exists(string name | - cls.lookupAttribute(name) = get_set | + exists(string name | cls.lookupAttribute(name) = get_set | name = "__get__" or name = "__set__" or name = "__delete__" ) and cls.lookupAttribute(_) = f and @@ -27,7 +26,7 @@ predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) { } from ClassObject cls, SelfAttributeStore s -where -mutates_descriptor(cls, s) - -select s, "Mutation of descriptor $@ object may lead to action-at-a-distance effects or race conditions for properties.", cls, cls.getName() \ No newline at end of file +where mutates_descriptor(cls, s) +select s, + "Mutation of descriptor $@ object may lead to action-at-a-distance effects or race conditions for properties.", + cls, cls.getName() diff --git a/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql b/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql index bd2be2ed379..168348e7b1c 100644 --- a/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql +++ b/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql @@ -13,59 +13,80 @@ import python - class InitCallStmt extends ExprStmt { - InitCallStmt() { exists(Call call, Attribute attr | call = this.getValue() and attr = call.getFunc() | - attr.getName() = "__init__") + attr.getName() = "__init__" + ) } - } predicate overwrites_which(Function subinit, AssignStmt write_attr, string which) { - write_attr.getScope() = subinit and self_write_stmt(write_attr, _) and + write_attr.getScope() = subinit and + self_write_stmt(write_attr, _) and exists(Stmt top | top.contains(write_attr) or top = write_attr | - (exists(int i, int j, InitCallStmt call | call.getScope() = subinit | i > j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "superclass") - or - exists(int i, int j, InitCallStmt call | call.getScope() = subinit | i < j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "subclass") - ) - ) + ( + exists(int i, int j, InitCallStmt call | call.getScope() = subinit | + i > j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "superclass" + ) + or + exists(int i, int j, InitCallStmt call | call.getScope() = subinit | + i < j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "subclass" + ) + ) + ) } predicate self_write_stmt(Stmt s, string attr) { - exists(Attribute a, Name self | self = a.getObject() and s.contains(a) and self.getId() = "self" and a.getCtx() instanceof Store and a.getName() = attr) + exists(Attribute a, Name self | + self = a.getObject() and + s.contains(a) and + self.getId() = "self" and + a.getCtx() instanceof Store and + a.getName() = attr + ) } predicate both_assign_attribute(Stmt s1, Stmt s2, Function f1, Function f2) { - exists(string name | s1.getScope() = f1 and s2.getScope() = f2 and self_write_stmt(s1, name) and self_write_stmt(s2, name)) + exists(string name | + s1.getScope() = f1 and + s2.getScope() = f2 and + self_write_stmt(s1, name) and + self_write_stmt(s2, name) + ) } -predicate attribute_overwritten(AssignStmt overwrites, AssignStmt overwritten, string name, string classtype, string classname) -{ - exists(FunctionObject superinit, FunctionObject subinit, ClassObject superclass, ClassObject subclass, AssignStmt subattr, AssignStmt superattr | - (classtype = "superclass" and classname = superclass.getName() and overwrites = subattr and overwritten = superattr or - classtype = "subclass" and classname = subclass.getName() and overwrites = superattr and overwritten = subattr) - and - /* OK if overwritten in subclass and is a class attribute */ - (not exists(superclass.declaredAttribute(name)) or classtype = "subclass") - and - superclass.declaredAttribute("__init__") = superinit - and - subclass.declaredAttribute("__init__") = subinit - and - superclass = subclass.getASuperType() - and - overwrites_which(subinit.getFunction(), subattr, classtype) - and - both_assign_attribute(subattr, superattr, subinit.getFunction(), superinit.getFunction()) - and - self_write_stmt(superattr, name) - ) +predicate attribute_overwritten( + AssignStmt overwrites, AssignStmt overwritten, string name, string classtype, string classname +) { + exists( + FunctionObject superinit, FunctionObject subinit, ClassObject superclass, ClassObject subclass, + AssignStmt subattr, AssignStmt superattr + | + ( + classtype = "superclass" and + classname = superclass.getName() and + overwrites = subattr and + overwritten = superattr + or + classtype = "subclass" and + classname = subclass.getName() and + overwrites = superattr and + overwritten = subattr + ) and + /* OK if overwritten in subclass and is a class attribute */ + (not exists(superclass.declaredAttribute(name)) or classtype = "subclass") and + superclass.declaredAttribute("__init__") = superinit and + subclass.declaredAttribute("__init__") = subinit and + superclass = subclass.getASuperType() and + overwrites_which(subinit.getFunction(), subattr, classtype) and + both_assign_attribute(subattr, superattr, subinit.getFunction(), superinit.getFunction()) and + self_write_stmt(superattr, name) + ) } - from string classtype, AssignStmt overwrites, AssignStmt overwritten, string name, string classname where attribute_overwritten(overwrites, overwritten, name, classtype, classname) - -select overwrites, "Assignment overwrites attribute " + name + ", which was previously defined in " + classtype + " $@.", overwritten, classname +select overwrites, + "Assignment overwrites attribute " + name + ", which was previously defined in " + classtype + + " $@.", overwritten, classname diff --git a/python/ql/src/Classes/PropertyInOldStyleClass.ql b/python/ql/src/Classes/PropertyInOldStyleClass.ql index fb2c822a573..ff2bf13a9f8 100644 --- a/python/ql/src/Classes/PropertyInOldStyleClass.ql +++ b/python/ql/src/Classes/PropertyInOldStyleClass.ql @@ -14,4 +14,6 @@ import python from PropertyObject prop, ClassObject cls where cls.declaredAttribute(_) = prop and not cls.failedInference() and not cls.isNewStyle() -select prop, "Property " + prop.getName() + " will not work properly, as class " + cls.getName() + " is an old-style class." +select prop, + "Property " + prop.getName() + " will not work properly, as class " + cls.getName() + + " is an old-style class." diff --git a/python/ql/src/Classes/ShouldBeContextManager.ql b/python/ql/src/Classes/ShouldBeContextManager.ql index d7394728935..e6bf946b65a 100644 --- a/python/ql/src/Classes/ShouldBeContextManager.ql +++ b/python/ql/src/Classes/ShouldBeContextManager.ql @@ -16,4 +16,6 @@ import python from ClassObject c where not c.isC() and not c.isContextManager() and exists(c.declaredAttribute("__del__")) -select c, "Class " + c.getName() + " implements __del__ (presumably to release some resource). Consider making it a context manager." +select c, + "Class " + c.getName() + + " implements __del__ (presumably to release some resource). Consider making it a context manager." diff --git a/python/ql/src/Classes/SubclassShadowing.ql b/python/ql/src/Classes/SubclassShadowing.ql index 6cdd9edf01d..ed1a79869b0 100644 --- a/python/ql/src/Classes/SubclassShadowing.ql +++ b/python/ql/src/Classes/SubclassShadowing.ql @@ -11,30 +11,36 @@ * @id py/attribute-shadows-method */ -/* Determine if a class defines a method that is shadowed by an attribute - defined in a super-class -*/ +/* + * Determine if a class defines a method that is shadowed by an attribute + * defined in a super-class + */ /* Need to find attributes defined in superclass (only in __init__?) */ - import python -predicate shadowed_by_super_class(ClassObject c, ClassObject supercls, Assign assign, FunctionObject f) -{ - c.getASuperType() = supercls and c.declaredAttribute(_) = f and +predicate shadowed_by_super_class( + ClassObject c, ClassObject supercls, Assign assign, FunctionObject f +) { + c.getASuperType() = supercls and + c.declaredAttribute(_) = f and exists(FunctionObject init, Attribute attr | supercls.declaredAttribute("__init__") = init and attr = assign.getATarget() and - ((Name)attr.getObject()).getId() = "self" and + attr.getObject().(Name).getId() = "self" and attr.getName() = f.getName() and - assign.getScope() = ((FunctionExpr)init.getOrigin()).getInnerScope() + assign.getScope() = init.getOrigin().(FunctionExpr).getInnerScope() ) and - /* It's OK if the super class defines the method as well. - * We assume that the original method must have been defined for a reason. */ + /* + * It's OK if the super class defines the method as well. + * We assume that the original method must have been defined for a reason. + */ + not supercls.hasAttribute(f.getName()) } from ClassObject c, ClassObject supercls, Assign assign, FunctionObject shadowed where shadowed_by_super_class(c, supercls, assign, shadowed) -select shadowed.getOrigin(), "Method " + shadowed.getName() + " is shadowed by $@ in super class '"+ supercls.getName() + "'.", assign, "an attribute" - +select shadowed.getOrigin(), + "Method " + shadowed.getName() + " is shadowed by $@ in super class '" + supercls.getName() + "'.", + assign, "an attribute" diff --git a/python/ql/src/Classes/SuperInOldStyleClass.ql b/python/ql/src/Classes/SuperInOldStyleClass.ql index b6c7649a1ca..aa4c62c6f08 100644 --- a/python/ql/src/Classes/SuperInOldStyleClass.ql +++ b/python/ql/src/Classes/SuperInOldStyleClass.ql @@ -13,10 +13,15 @@ import python predicate uses_of_super_in_old_style_class(Call s) { - exists(Function f, ClassObject c | s.getScope() = f and f.getScope() = c.getPyClass() and not c.failedInference() and - not c.isNewStyle() and ((Name)s.getFunc()).getId() = "super") + exists(Function f, ClassObject c | + s.getScope() = f and + f.getScope() = c.getPyClass() and + not c.failedInference() and + not c.isNewStyle() and + s.getFunc().(Name).getId() = "super" + ) } from Call c where uses_of_super_in_old_style_class(c) -select c, "super() will not work in old-style classes" \ No newline at end of file +select c, "super() will not work in old-style classes" diff --git a/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql b/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql index b0e4a13469d..cd4c74a5e86 100644 --- a/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql +++ b/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql @@ -13,15 +13,16 @@ import python import MethodCallOrder - from ClassObject self, FunctionObject multi -where -multiple_calls_to_superclass_method(self, multi, "__del__") and -not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__del__") and -not exists(FunctionObject better | - multiple_calls_to_superclass_method(self, better, "__del__") and - better.overrides(multi) -) and -not self.failedInference() -select self, "Class " + self.getName() + " may not be cleaned up properly as $@ may be called multiple times during destruction.", -multi, multi.descriptiveString() +where + multiple_calls_to_superclass_method(self, multi, "__del__") and + not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__del__") and + not exists(FunctionObject better | + multiple_calls_to_superclass_method(self, better, "__del__") and + better.overrides(multi) + ) and + not self.failedInference() +select self, + "Class " + self.getName() + + " may not be cleaned up properly as $@ may be called multiple times during destruction.", multi, + multi.descriptiveString() diff --git a/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql b/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql index 723527e1de8..71d05533fde 100644 --- a/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql +++ b/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql @@ -14,13 +14,16 @@ import python import MethodCallOrder from ClassObject self, FunctionObject multi -where multi != theObjectType().lookupAttribute("__init__") and -multiple_calls_to_superclass_method(self, multi, "__init__") and -not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__init__") and -not exists(FunctionObject better | - multiple_calls_to_superclass_method(self, better, "__init__") and - better.overrides(multi) -) and -not self.failedInference() -select self, "Class " + self.getName() + " may not be initialized properly as $@ may be called multiple times during initialization.", -multi, multi.descriptiveString() +where + multi != theObjectType().lookupAttribute("__init__") and + multiple_calls_to_superclass_method(self, multi, "__init__") and + not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__init__") and + not exists(FunctionObject better | + multiple_calls_to_superclass_method(self, better, "__init__") and + better.overrides(multi) + ) and + not self.failedInference() +select self, + "Class " + self.getName() + + " may not be initialized properly as $@ may be called multiple times during initialization.", + multi, multi.descriptiveString() diff --git a/python/ql/src/Classes/UndefinedClassAttribute.ql b/python/ql/src/Classes/UndefinedClassAttribute.ql index 6619fd031eb..bdbbcbf2496 100644 --- a/python/ql/src/Classes/UndefinedClassAttribute.ql +++ b/python/ql/src/Classes/UndefinedClassAttribute.ql @@ -32,4 +32,3 @@ predicate report_undefined_class_attribute(Attribute a, ClassObject c, string na from Attribute a, ClassObject c, string name where report_undefined_class_attribute(a, c, name) select a, "Attribute '" + name + "' is not defined in either the class body or in any method" - diff --git a/python/ql/src/Classes/UselessClass.ql b/python/ql/src/Classes/UselessClass.ql index e04ea103ad6..2c872420049 100644 --- a/python/ql/src/Classes/UselessClass.ql +++ b/python/ql/src/Classes/UselessClass.ql @@ -21,63 +21,68 @@ predicate does_not_define_special_method(Class cls) { not exists(Function f | f = cls.getAMethod() and f.isSpecialMethod()) } - predicate no_inheritance(Class c) { not exists(ClassObject cls, ClassObject other | - cls.getPyClass() = c and - other != theObjectType() | + cls.getPyClass() = c and + other != theObjectType() + | other.getABaseType() = cls or cls.getABaseType() = other - ) - and + ) and not exists(Expr base | base = c.getABase() | - not base instanceof Name or ((Name)base).getId() != "object" + not base instanceof Name or base.(Name).getId() != "object" ) } -predicate is_decorated(Class c) { - exists(c.getADecorator()) -} +predicate is_decorated(Class c) { exists(c.getADecorator()) } predicate is_stateful(Class c) { - exists(Function method, ExprContext ctx | - method.getScope() = c and (ctx instanceof Store or ctx instanceof AugStore) | + exists(Function method, ExprContext ctx | + method.getScope() = c and + (ctx instanceof Store or ctx instanceof AugStore) + | exists(Subscript s | s.getScope() = method and s.getCtx() = ctx) or exists(Attribute a | a.getScope() = method and a.getCtx() = ctx) ) or - exists(Function method, Call call, Attribute a, string name | - method.getScope() = c and call.getScope() = method and - call.getFunc() = a and a.getName() = name | - name = "pop" or name = "remove" or name = "discard" or - name = "extend" or name = "append" + exists(Function method, Call call, Attribute a, string name | + method.getScope() = c and + call.getScope() = method and + call.getFunc() = a and + a.getName() = name + | + name = "pop" or + name = "remove" or + name = "discard" or + name = "extend" or + name = "append" ) - } predicate useless_class(Class c, int methods) { - c.isTopLevel() - and - c.isPublic() - and - no_inheritance(c) - and - fewer_than_two_public_methods(c, methods) - and - does_not_define_special_method(c) - and - not c.isProbableMixin() - and - not is_decorated(c) - and + c.isTopLevel() and + c.isPublic() and + no_inheritance(c) and + fewer_than_two_public_methods(c, methods) and + does_not_define_special_method(c) and + not c.isProbableMixin() and + not is_decorated(c) and not is_stateful(c) } from Class c, int methods, string msg -where useless_class(c, methods) and -(methods = 1 and msg = "Class " + c.getName() + " defines only one public method, which should be replaced by a function." - or - methods = 0 and msg = "Class " + c.getName() + " defines no public methods and could be replaced with a namedtuple or dictionary." -) +where + useless_class(c, methods) and + ( + methods = 1 and + msg = + "Class " + c.getName() + + " defines only one public method, which should be replaced by a function." + or + methods = 0 and + msg = + "Class " + c.getName() + + " defines no public methods and could be replaced with a namedtuple or dictionary." + ) select c, msg diff --git a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql index 022d6a515e6..3ac4454a019 100644 --- a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql @@ -14,14 +14,11 @@ */ import python - import Expressions.CallArgs - from Call call, ClassObject cls, string name, FunctionObject init where - illegally_named_parameter_objectapi(call, cls, name) - and init = get_function_or_initializer_objectapi(cls) -select - call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", init, init.getQualifiedName() - + illegally_named_parameter_objectapi(call, cls, name) and + init = get_function_or_initializer_objectapi(cls) +select call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", init, + init.getQualifiedName() diff --git a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql index f94b5ac5b3e..f04d2350855 100644 --- a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql @@ -17,9 +17,15 @@ import Expressions.CallArgs from Call call, ClassObject cls, string too, string should, int limit, FunctionObject init where -( - too_many_args_objectapi(call, cls, limit) and too = "too many arguments" and should = "no more than " - or - too_few_args_objectapi(call, cls, limit) and too = "too few arguments" and should = "no fewer than " -) and init = get_function_or_initializer_objectapi(cls) -select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", init, init.getQualifiedName() + ( + too_many_args_objectapi(call, cls, limit) and + too = "too many arguments" and + should = "no more than " + or + too_few_args_objectapi(call, cls, limit) and + too = "too few arguments" and + should = "no fewer than " + ) and + init = get_function_or_initializer_objectapi(cls) +select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", init, + init.getQualifiedName() diff --git a/python/ql/src/Exceptions/CatchingBaseException.ql b/python/ql/src/Exceptions/CatchingBaseException.ql index d175297f1c9..04a95a8e827 100644 --- a/python/ql/src/Exceptions/CatchingBaseException.ql +++ b/python/ql/src/Exceptions/CatchingBaseException.ql @@ -14,17 +14,16 @@ import python -predicate doesnt_reraise(ExceptStmt ex) { - ex.getAFlowNode().getBasicBlock().reachesExit() -} +predicate doesnt_reraise(ExceptStmt ex) { ex.getAFlowNode().getBasicBlock().reachesExit() } predicate catches_base_exception(ExceptStmt ex) { - ex.getType().pointsTo(ClassValue::baseException()) - or - not exists(ex.getType()) + ex.getType().pointsTo(ClassValue::baseException()) + or + not exists(ex.getType()) } from ExceptStmt ex -where catches_base_exception(ex) and -doesnt_reraise(ex) +where + catches_base_exception(ex) and + doesnt_reraise(ex) select ex, "Except block directly handles BaseException." diff --git a/python/ql/src/Exceptions/EmptyExcept.ql b/python/ql/src/Exceptions/EmptyExcept.ql index a753181af71..fd656755c1c 100755 --- a/python/ql/src/Exceptions/EmptyExcept.ql +++ b/python/ql/src/Exceptions/EmptyExcept.ql @@ -13,21 +13,18 @@ import python -predicate -empty_except(ExceptStmt ex) { +predicate empty_except(ExceptStmt ex) { not exists(Stmt s | s = ex.getAStmt() and not s instanceof Pass) } -predicate no_else(ExceptStmt ex) { - not exists(ex.getTry().getOrelse()) -} +predicate no_else(ExceptStmt ex) { not exists(ex.getTry().getOrelse()) } predicate no_comment(ExceptStmt ex) { - not exists(Comment c | - c.getLocation().getFile() = ex.getLocation().getFile() and - c.getLocation().getStartLine() >= ex.getLocation().getStartLine() and - c.getLocation().getEndLine() <= ex.getBody().getLastItem().getLocation().getEndLine() - ) + not exists(Comment c | + c.getLocation().getFile() = ex.getLocation().getFile() and + c.getLocation().getStartLine() >= ex.getLocation().getStartLine() and + c.getLocation().getEndLine() <= ex.getBody().getLastItem().getLocation().getEndLine() + ) } predicate non_local_control_flow(ExceptStmt ex) { @@ -38,7 +35,8 @@ predicate try_has_normal_exit(Try try) { exists(ControlFlowNode pred, ControlFlowNode succ | /* Exists a non-exception predecessor, successor pair */ pred.getASuccessor() = succ and - not pred.getAnExceptionalSuccessor() = succ | + not pred.getAnExceptionalSuccessor() = succ + | /* Successor is either a normal flow node or a fall-through exit */ not exists(Scope s | s.getReturnNode() = succ) and /* Predecessor is in try body and successor is not */ @@ -50,8 +48,7 @@ predicate try_has_normal_exit(Try try) { predicate attribute_access(Stmt s) { s.(ExprStmt).getValue() instanceof Attribute or - exists(string name | - s.(ExprStmt).getValue().(Call).getFunc().(Name).getId() = name | + exists(string name | s.(ExprStmt).getValue().(Call).getFunc().(Name).getId() = name | name = "getattr" or name = "setattr" or name = "delattr" ) or @@ -65,8 +62,7 @@ predicate subscript(Stmt s) { } predicate encode_decode(Call ex, ClassValue type) { - exists(string name | - ex.getFunc().(Attribute).getName() = name | + exists(string name | ex.getFunc().(Attribute).getName() = name | name = "encode" and type = ClassValue::unicodeEncodeError() or name = "decode" and type = ClassValue::unicodeDecodeError() @@ -80,8 +76,7 @@ predicate small_handler(ExceptStmt ex, Stmt s, ClassValue type) { } predicate focussed_handler(ExceptStmt ex) { - exists(Stmt s, ClassValue type | - small_handler(ex, s, type) | + exists(Stmt s, ClassValue type | small_handler(ex, s, type) | subscript(s) and type.getASuperType() = ClassValue::lookupError() or attribute_access(s) and type = ClassValue::attributeError() @@ -92,12 +87,15 @@ predicate focussed_handler(ExceptStmt ex) { ) } -Try try_return() { - not exists(result.getStmt(1)) and result.getStmt(0) instanceof Return -} +Try try_return() { not exists(result.getStmt(1)) and result.getStmt(0) instanceof Return } from ExceptStmt ex -where empty_except(ex) and no_else(ex) and no_comment(ex) and not non_local_control_flow(ex) - and not ex.getTry() = try_return() and try_has_normal_exit(ex.getTry()) and - not focussed_handler(ex) +where + empty_except(ex) and + no_else(ex) and + no_comment(ex) and + not non_local_control_flow(ex) and + not ex.getTry() = try_return() and + try_has_normal_exit(ex.getTry()) and + not focussed_handler(ex) select ex, "'except' clause does nothing but pass and there is no explanatory comment." diff --git a/python/ql/src/Exceptions/IllegalRaise.ql b/python/ql/src/Exceptions/IllegalRaise.ql index da1bc56ae33..f05f5437db2 100644 --- a/python/ql/src/Exceptions/IllegalRaise.ql +++ b/python/ql/src/Exceptions/IllegalRaise.ql @@ -16,6 +16,10 @@ import Raising import Exceptions.NotImplemented from Raise r, ClassValue t -where type_or_typeof(r, t, _) and not t.isLegalExceptionType() and not t.failedInference(_) and not use_of_not_implemented_in_raise(r, _) -select r, "Illegal class '" + t.getName() + "' raised; will result in a TypeError being raised instead." - +where + type_or_typeof(r, t, _) and + not t.isLegalExceptionType() and + not t.failedInference(_) and + not use_of_not_implemented_in_raise(r, _) +select r, + "Illegal class '" + t.getName() + "' raised; will result in a TypeError being raised instead." diff --git a/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql b/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql index 89f1bb04568..933d15ddf60 100644 --- a/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql +++ b/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql @@ -15,5 +15,4 @@ import Exceptions.NotImplemented from Expr notimpl where use_of_not_implemented_in_raise(_, notimpl) - select notimpl, "NotImplemented is not an Exception. Did you mean NotImplementedError?" diff --git a/python/ql/src/Exceptions/RaisingTuple.ql b/python/ql/src/Exceptions/RaisingTuple.ql index ab197fe1665..dc4b295a90d 100644 --- a/python/ql/src/Exceptions/RaisingTuple.ql +++ b/python/ql/src/Exceptions/RaisingTuple.ql @@ -12,8 +12,11 @@ import python from Raise r, Value v, AstNode origin -where r.getException().pointsTo(v, origin) and -v.getClass() = ClassValue::tuple() and -major_version() = 2 /* Raising a tuple is a type error in Python 3, so is handled by the IllegalRaise query. */ - -select r, "Raising $@ will result in the first element (recursively) being raised and all other elements being discarded.", origin, "a tuple" \ No newline at end of file +where + r.getException().pointsTo(v, origin) and + v.getClass() = ClassValue::tuple() and + major_version() = 2 +/* Raising a tuple is a type error in Python 3, so is handled by the IllegalRaise query. */ +select r, + "Raising $@ will result in the first element (recursively) being raised and all other elements being discarded.", + origin, "a tuple" diff --git a/python/ql/src/Exceptions/UnguardedNextInGenerator.ql b/python/ql/src/Exceptions/UnguardedNextInGenerator.ql index ff0f53dea4d..c2435d41b3e 100755 --- a/python/ql/src/Exceptions/UnguardedNextInGenerator.ql +++ b/python/ql/src/Exceptions/UnguardedNextInGenerator.ql @@ -12,13 +12,9 @@ import python -FunctionValue iter() { - result = Value::named("iter") -} +FunctionValue iter() { result = Value::named("iter") } -BuiltinFunctionValue next() { - result = Value::named("next") -} +BuiltinFunctionValue next() { result = Value::named("next") } predicate call_to_iter(CallNode call, EssaVariable sequence) { sequence.getAUse() = iter().getArgumentForCall(call, 0) @@ -52,14 +48,14 @@ predicate stop_iteration_handled(CallNode call) { } from CallNode call -where call_to_next(call, _) and -not call_to_next_has_default(call) and -not exists(EssaVariable iterator | - call_to_next(call, iterator.getAUse()) and - iter_not_exhausted(iterator) -) and -call.getNode().getScope().(Function).isGenerator() and -not exists(Comp comp | comp.contains(call.getNode())) and -not stop_iteration_handled(call) - +where + call_to_next(call, _) and + not call_to_next_has_default(call) and + not exists(EssaVariable iterator | + call_to_next(call, iterator.getAUse()) and + iter_not_exhausted(iterator) + ) and + call.getNode().getScope().(Function).isGenerator() and + not exists(Comp comp | comp.contains(call.getNode())) and + not stop_iteration_handled(call) select call, "Call to next() in a generator" diff --git a/python/ql/src/Expressions/CallToSuperWrongClass.ql b/python/ql/src/Expressions/CallToSuperWrongClass.ql index 57ae36fa30e..4f218ab5a2c 100644 --- a/python/ql/src/Expressions/CallToSuperWrongClass.ql +++ b/python/ql/src/Expressions/CallToSuperWrongClass.ql @@ -16,14 +16,14 @@ import python from CallNode call_to_super, string name where -exists(GlobalVariable gv, ControlFlowNode cn | - call_to_super = ClassValue::super_().getACall() and - gv.getId() = "super" and - cn = call_to_super.getArg(0) and - name = call_to_super.getScope().getScope().(Class).getName() and - exists(ClassValue other | - cn.pointsTo(other) and - not other.getScope().getName() = name + exists(GlobalVariable gv, ControlFlowNode cn | + call_to_super = ClassValue::super_().getACall() and + gv.getId() = "super" and + cn = call_to_super.getArg(0) and + name = call_to_super.getScope().getScope().(Class).getName() and + exists(ClassValue other | + cn.pointsTo(other) and + not other.getScope().getName() = name + ) ) -) select call_to_super.getNode(), "First argument to super() should be " + name + "." diff --git a/python/ql/src/Expressions/CompareConstants.ql b/python/ql/src/Expressions/CompareConstants.ql index 2a66a952c5e..5b04302db31 100644 --- a/python/ql/src/Expressions/CompareConstants.ql +++ b/python/ql/src/Expressions/CompareConstants.ql @@ -16,6 +16,8 @@ import python from Compare comparison, Expr left, Expr right where - comparison.compares(left, _, right) and left.isConstant() and right.isConstant() and + comparison.compares(left, _, right) and + left.isConstant() and + right.isConstant() and not exists(Assert a | a.getTest() = comparison) select comparison, "Comparison of constants; use 'True' or 'False' instead." diff --git a/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql b/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql index 9d618c2dbb1..554d7a087b6 100644 --- a/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql +++ b/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql @@ -16,6 +16,5 @@ import python import Expressions.RedundantComparison from RedundantComparison comparison -where - comparison.maybeMissingSelf() +where comparison.maybeMissingSelf() select comparison, "Comparison of identical values; may be missing 'self'." diff --git a/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql b/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql index 1a1083884ea..29f21e7beb2 100644 --- a/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql +++ b/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql @@ -15,16 +15,19 @@ import python import semmle.python.Comparisons -/* Holds if the comparison `comp` is of the complex form `a op b op c` and not of +/* + * Holds if the comparison `comp` is of the complex form `a op b op c` and not of * the simple form `a op b`. */ + private predicate is_complex(Expr comp) { exists(comp.(Compare).getOp(1)) or is_complex(comp.(UnaryExpr).getOperand()) } -/** A test is useless if for every block that it controls there is another test that is at least as +/** + * A test is useless if for every block that it controls there is another test that is at least as * strict and also controls that block. */ private predicate useless_test(Comparison comp, ComparisonControlBlock controls, boolean isTrue) { @@ -34,17 +37,15 @@ private predicate useless_test(Comparison comp, ComparisonControlBlock controls, } private predicate useless_test_ast(AstNode comp, AstNode previous, boolean isTrue) { - forex(Comparison compnode, ConditionBlock block| + forex(Comparison compnode, ConditionBlock block | compnode.getNode() = comp and block.getLastNode().getNode() = previous - | + | useless_test(compnode, block, isTrue) ) } from Expr test, Expr other, boolean isTrue -where -useless_test_ast(test, other, isTrue) and not useless_test_ast(test.getAChildNode+(), other, _) - - +where + useless_test_ast(test, other, isTrue) and not useless_test_ast(test.getAChildNode+(), other, _) select test, "Test is always " + isTrue + ", because of $@", other, "this condition" diff --git a/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql b/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql index 20678da8dc0..99a1a0e44e1 100644 --- a/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql +++ b/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql @@ -17,13 +17,12 @@ import semmle.python.strings predicate dict_key(Dict d, Expr k, string s) { k = d.getAKey() and ( - s = ((Num)k).getN() + s = k.(Num).getN() or // We use � to mark unrepresentable characters // so two instances of � may represent different strings in the source code not "�" = s.charAt(_) and - exists(StrConst c | - c = k | + exists(StrConst c | c = k | s = "u\"" + c.getText() + "\"" and c.isUnicode() or s = "b\"" + c.getText() + "\"" and not c.isUnicode() @@ -32,13 +31,15 @@ predicate dict_key(Dict d, Expr k, string s) { } from Dict d, Expr k1, Expr k2 -where exists(string s | dict_key(d, k1, s) and dict_key(d, k2, s) and k1 != k2) and -( - exists(BasicBlock b, int i1, int i2 | - k1.getAFlowNode() = b.getNode(i1) and - k2.getAFlowNode() = b.getNode(i2) and - i1 < i2 - ) or - k1.getAFlowNode().getBasicBlock().strictlyDominates(k2.getAFlowNode().getBasicBlock()) -) +where + exists(string s | dict_key(d, k1, s) and dict_key(d, k2, s) and k1 != k2) and + ( + exists(BasicBlock b, int i1, int i2 | + k1.getAFlowNode() = b.getNode(i1) and + k2.getAFlowNode() = b.getNode(i2) and + i1 < i2 + ) + or + k1.getAFlowNode().getBasicBlock().strictlyDominates(k2.getAFlowNode().getBasicBlock()) + ) select k1, "Dictionary key " + repr(k1) + " is subsequently $@.", k2, "overwritten" diff --git a/python/ql/src/Expressions/ExplicitCallToDel.ql b/python/ql/src/Expressions/ExplicitCallToDel.ql index 1cb2782c885..81e8fc97b43 100644 --- a/python/ql/src/Expressions/ExplicitCallToDel.ql +++ b/python/ql/src/Expressions/ExplicitCallToDel.ql @@ -13,23 +13,22 @@ import python class DelCall extends Call { - DelCall() { - ((Attribute)this.getFunc()).getName() = "__del__" - } - - predicate isSuperCall() { - exists(Function f | f = this.getScope() and f.getName() = "__del__" | - // We pass in `self` as the first argument... - f.getArg(0).asName().getVariable() = ((Name)this.getArg(0)).getVariable() or - // ... or the call is of the form `super(Type, self).__del__()`, or the equivalent - // Python 3: `super().__del__()`. - exists(Call superCall | superCall = ((Attribute)this.getFunc()).getObject() | - ((Name)superCall.getFunc()).getId() = "super" - ) - ) - } + DelCall() { this.getFunc().(Attribute).getName() = "__del__" } + + predicate isSuperCall() { + exists(Function f | f = this.getScope() and f.getName() = "__del__" | + // We pass in `self` as the first argument... + f.getArg(0).asName().getVariable() = this.getArg(0).(Name).getVariable() + or + // ... or the call is of the form `super(Type, self).__del__()`, or the equivalent + // Python 3: `super().__del__()`. + exists(Call superCall | superCall = this.getFunc().(Attribute).getObject() | + superCall.getFunc().(Name).getId() = "super" + ) + ) + } } from DelCall del where not del.isSuperCall() -select del, "The __del__ special method is called explicitly." \ No newline at end of file +select del, "The __del__ special method is called explicitly." diff --git a/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql b/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql index 3f488aa9507..a52fada69b0 100644 --- a/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql +++ b/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql @@ -15,4 +15,4 @@ import AdvancedFormatting from AdvancedFormattingCall call, AdvancedFormatString fmt where call.getAFormat() = fmt and fmt.isImplicitlyNumbered() and fmt.isExplicitlyNumbered() -select fmt, "Formatting string mixes implicitly and explicitly numbered fields." \ No newline at end of file +select fmt, "Formatting string mixes implicitly and explicitly numbered fields." diff --git a/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql b/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql index 67c95277375..89af180099d 100644 --- a/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql +++ b/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql @@ -11,16 +11,18 @@ */ import python - - import python import AdvancedFormatting int field_count(AdvancedFormatString fmt) { result = max(fmt.getFieldNumber(_, _)) + 1 } from AdvancedFormattingCall call, AdvancedFormatString fmt, int arg_count, int max_field -where arg_count = call.providedArgCount() and max_field = field_count(fmt) and -call.getAFormat() = fmt and not exists(call.getStarargs()) and -forall(AdvancedFormatString other | other = call.getAFormat() | field_count(other) < arg_count) -select call, "Too many arguments for string format. Format $@ requires only " + max_field + ", but " + -arg_count.toString() + " are provided.", fmt, "\"" + fmt.getText() + "\"" +where + arg_count = call.providedArgCount() and + max_field = field_count(fmt) and + call.getAFormat() = fmt and + not exists(call.getStarargs()) and + forall(AdvancedFormatString other | other = call.getAFormat() | field_count(other) < arg_count) +select call, + "Too many arguments for string format. Format $@ requires only " + max_field + ", but " + + arg_count.toString() + " are provided.", fmt, "\"" + fmt.getText() + "\"" diff --git a/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql b/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql index c902b992b1c..62c598a397e 100644 --- a/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql +++ b/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql @@ -14,14 +14,18 @@ import python import AdvancedFormatting from AdvancedFormattingCall call, AdvancedFormatString fmt, string name, string fmt_repr -where call.getAFormat() = fmt and -name = call.getAKeyword().getArg() and -forall(AdvancedFormatString format | format = call.getAFormat() | not format.getFieldName(_, _) = name) -and not exists(call.getKwargs()) and -(strictcount(call.getAFormat()) = 1 and fmt_repr = "format \"" + fmt.getText() + "\"" - or - strictcount(call.getAFormat()) != 1 and fmt_repr = "any format used." -) - -select call, "Surplus named argument for string format. An argument named '" + name + - "' is provided, but it is not required by $@.", fmt, fmt_repr +where + call.getAFormat() = fmt and + name = call.getAKeyword().getArg() and + forall(AdvancedFormatString format | format = call.getAFormat() | + not format.getFieldName(_, _) = name + ) and + not exists(call.getKwargs()) and + ( + strictcount(call.getAFormat()) = 1 and fmt_repr = "format \"" + fmt.getText() + "\"" + or + strictcount(call.getAFormat()) != 1 and fmt_repr = "any format used." + ) +select call, + "Surplus named argument for string format. An argument named '" + name + + "' is provided, but it is not required by $@.", fmt, fmt_repr diff --git a/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql b/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql index 412d8d55830..384d9b9d58e 100644 --- a/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql +++ b/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql @@ -15,9 +15,11 @@ import python import AdvancedFormatting from AdvancedFormattingCall call, AdvancedFormatString fmt, string name -where call.getAFormat() = fmt and -not name = call.getAKeyword().getArg() and -fmt.getFieldName(_, _) = name -and not exists(call.getKwargs()) -select call, "Missing named argument for string format. Format $@ requires '" + name + "', but it is omitted.", -fmt, "\"" + fmt.getText() + "\"" \ No newline at end of file +where + call.getAFormat() = fmt and + not name = call.getAKeyword().getArg() and + fmt.getFieldName(_, _) = name and + not exists(call.getKwargs()) +select call, + "Missing named argument for string format. Format $@ requires '" + name + "', but it is omitted.", + fmt, "\"" + fmt.getText() + "\"" diff --git a/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql b/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql index fe766ae2d8b..8f3479c5be5 100644 --- a/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql +++ b/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql @@ -14,10 +14,16 @@ import python import AdvancedFormatting -from AdvancedFormattingCall call, AdvancedFormatString fmt, -int arg_count, int max_field, string provided -where arg_count = call.providedArgCount() and max_field = max(fmt.getFieldNumber(_, _)) and -call.getAFormat() = fmt and not exists(call.getStarargs()) and arg_count <= max_field and -(if arg_count = 1 then provided = " is provided." else provided = " are provided.") -select call, "Too few arguments for string format. Format $@ requires at least " + (max_field+1) + ", but " + -arg_count.toString() + provided, fmt, "\"" + fmt.getText() + "\"" \ No newline at end of file +from + AdvancedFormattingCall call, AdvancedFormatString fmt, int arg_count, int max_field, + string provided +where + arg_count = call.providedArgCount() and + max_field = max(fmt.getFieldNumber(_, _)) and + call.getAFormat() = fmt and + not exists(call.getStarargs()) and + arg_count <= max_field and + (if arg_count = 1 then provided = " is provided." else provided = " are provided.") +select call, + "Too few arguments for string format. Format $@ requires at least " + (max_field + 1) + ", but " + + arg_count.toString() + provided, fmt, "\"" + fmt.getText() + "\"" diff --git a/python/ql/src/Expressions/HashedButNoHash.ql b/python/ql/src/Expressions/HashedButNoHash.ql index 37da9407b7f..7fbb723fc54 100644 --- a/python/ql/src/Expressions/HashedButNoHash.ql +++ b/python/ql/src/Expressions/HashedButNoHash.ql @@ -12,7 +12,8 @@ import python -/* This assumes that any indexing operation where the value is not a sequence or numpy array involves hashing. +/* + * This assumes that any indexing operation where the value is not a sequence or numpy array involves hashing. * For sequences, the index must be an int, which are hashable, so we don't need to treat them specially. * For numpy arrays, the index may be a list, which are not hashable and needs to be treated specially. */ @@ -30,7 +31,9 @@ predicate has_custom_getitem(Value v) { } predicate explicitly_hashed(ControlFlowNode f) { - exists(CallNode c, GlobalVariable hash | c.getArg(0) = f and c.getFunction().(NameNode).uses(hash) and hash.getId() = "hash") + exists(CallNode c, GlobalVariable hash | + c.getArg(0) = f and c.getFunction().(NameNode).uses(hash) and hash.getId() = "hash" + ) } predicate unhashable_subscript(ControlFlowNode f, ClassValue c, ControlFlowNode origin) { @@ -44,9 +47,7 @@ predicate unhashable_subscript(ControlFlowNode f, ClassValue c, ControlFlowNode } predicate is_unhashable(ControlFlowNode f, ClassValue cls, ControlFlowNode origin) { - exists(Value v | - f.pointsTo(v, origin) and v.getClass() = cls - | + exists(Value v | f.pointsTo(v, origin) and v.getClass() = cls | not cls.hasAttribute("__hash__") and not cls.failedInference(_) and cls.isNewStyle() or cls.lookup("__hash__") = Value::named("None") @@ -67,16 +68,18 @@ predicate is_unhashable(ControlFlowNode f, ClassValue cls, ControlFlowNode origi * it. */ predicate typeerror_is_caught(ControlFlowNode f) { - exists (Try try | + exists(Try try | try.getBody().contains(f.getNode()) and - try.getAHandler().getType().pointsTo(ClassValue::typeError())) + try.getAHandler().getType().pointsTo(ClassValue::typeError()) + ) } from ControlFlowNode f, ClassValue c, ControlFlowNode origin where -not typeerror_is_caught(f) -and -(explicitly_hashed(f) and is_unhashable(f, c, origin) - or - unhashable_subscript(f, c, origin)) + not typeerror_is_caught(f) and + ( + explicitly_hashed(f) and is_unhashable(f, c, origin) + or + unhashable_subscript(f, c, origin) + ) select f.getNode(), "This $@ of $@ is unhashable.", origin, "instance", c, c.getQualifiedName() diff --git a/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql b/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql index 2a2025ec51e..5dda5b857f9 100644 --- a/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql +++ b/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql @@ -14,7 +14,14 @@ import python import IsComparisons from Compare comp, Cmpop op, ClassValue c, string alt -where invalid_portable_is_comparison(comp, op, c) and -not cpython_interned_constant(comp.getASubExpression()) and -(op instanceof Is and alt = "==" or op instanceof IsNot and alt = "!=") -select comp, "Values compared using '" + op.getSymbol() + "' when equivalence is not the same as identity. Use '" + alt + "' instead." +where + invalid_portable_is_comparison(comp, op, c) and + not cpython_interned_constant(comp.getASubExpression()) and + ( + op instanceof Is and alt = "==" + or + op instanceof IsNot and alt = "!=" + ) +select comp, + "Values compared using '" + op.getSymbol() + + "' when equivalence is not the same as identity. Use '" + alt + "' instead." diff --git a/python/ql/src/Expressions/NonCallableCalled.ql b/python/ql/src/Expressions/NonCallableCalled.ql index 2f9a0f8f5cc..fdd0bbd13c3 100644 --- a/python/ql/src/Expressions/NonCallableCalled.ql +++ b/python/ql/src/Expressions/NonCallableCalled.ql @@ -15,10 +15,13 @@ import python import Exceptions.NotImplemented from Call c, Value v, ClassValue t, Expr f, AstNode origin -where f = c.getFunc() and f.pointsTo(v, origin) and t = v.getClass() and - not t.isCallable() and not t.failedInference(_) - and not t.hasAttribute("__get__") - and not v = Value::named("None") - and not use_of_not_implemented_in_raise(_, f) - +where + f = c.getFunc() and + f.pointsTo(v, origin) and + t = v.getClass() and + not t.isCallable() and + not t.failedInference(_) and + not t.hasAttribute("__get__") and + not v = Value::named("None") and + not use_of_not_implemented_in_raise(_, f) select c, "Call to a $@ of $@.", origin, "non-callable", t, t.toString() diff --git a/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql b/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql index d5aefebd3ce..3e01ccdacf7 100644 --- a/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql +++ b/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql @@ -14,10 +14,12 @@ import python import IsComparisons from Compare comp, Cmpop op, ClassValue c -where invalid_portable_is_comparison(comp, op, c) and -exists(Expr sub | - sub = comp.getASubExpression() | - cpython_interned_constant(sub) and - not universally_interned_constant(sub) -) -select comp, "The result of this comparison with '" + op.getSymbol() + "' may differ between implementations of Python." \ No newline at end of file +where + invalid_portable_is_comparison(comp, op, c) and + exists(Expr sub | sub = comp.getASubExpression() | + cpython_interned_constant(sub) and + not universally_interned_constant(sub) + ) +select comp, + "The result of this comparison with '" + op.getSymbol() + + "' may differ between implementations of Python." diff --git a/python/ql/src/Expressions/Regex/BackspaceEscape.ql b/python/ql/src/Expressions/Regex/BackspaceEscape.ql index b80893b04f0..b18d581257a 100644 --- a/python/ql/src/Expressions/Regex/BackspaceEscape.ql +++ b/python/ql/src/Expressions/Regex/BackspaceEscape.ql @@ -14,9 +14,8 @@ import python import semmle.python.regex from Regex r, int offset -where r.escapingChar(offset) and r.getChar(offset+1) = "b" and -exists(int start, int end | - start < offset and end > offset | - r.charSet(start, end) -) -select r, "Backspace escape in regular expression at offset " + offset + "." \ No newline at end of file +where + r.escapingChar(offset) and + r.getChar(offset + 1) = "b" and + exists(int start, int end | start < offset and end > offset | r.charSet(start, end)) +select r, "Backspace escape in regular expression at offset " + offset + "." diff --git a/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql b/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql index 88c265fb370..42a745affb8 100644 --- a/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql +++ b/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql @@ -15,20 +15,28 @@ import semmle.python.regex predicate duplicate_char_in_class(Regex r, string char) { exists(int i, int j, int x, int y, int start, int end | - i != x and j != y and - start < i and j < end and - start < x and y < end and - r.character(i, j) and char = r.getText().substring(i, j) and - r.character(x, y) and char = r.getText().substring(x, y) and + i != x and + j != y and + start < i and + j < end and + start < x and + y < end and + r.character(i, j) and + char = r.getText().substring(i, j) and + r.character(x, y) and + char = r.getText().substring(x, y) and r.charSet(start, end) ) and /* Exclude � as we use it for any unencodable character */ char != "�" and //Ignore whitespace in verbose mode - not (r.getAMode() = "VERBOSE" and (char = " " or char = "\t" or char = "\r" or char = "\n")) + not ( + r.getAMode() = "VERBOSE" and + (char = " " or char = "\t" or char = "\r" or char = "\n") + ) } from Regex r, string char where duplicate_char_in_class(r, char) -select r, "This regular expression includes duplicate character '" + char + "' in a set of characters." - +select r, + "This regular expression includes duplicate character '" + char + "' in a set of characters." diff --git a/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql b/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql index 7a1974fc514..ea5deffa7de 100644 --- a/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql +++ b/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql @@ -16,5 +16,3 @@ import semmle.python.regex from Regex r, string missing, string part where r.getText().regexpMatch(".*\\(P<\\w+>.*") and missing = "?" and part = "named group" select r, "Regular expression is missing '" + missing + "' in " + part + "." - - diff --git a/python/ql/src/Expressions/Regex/UnmatchableCaret.ql b/python/ql/src/Expressions/Regex/UnmatchableCaret.ql index 7fc0c6f219e..7a5c087ec02 100644 --- a/python/ql/src/Expressions/Regex/UnmatchableCaret.ql +++ b/python/ql/src/Expressions/Regex/UnmatchableCaret.ql @@ -16,10 +16,11 @@ import semmle.python.regex predicate unmatchable_caret(Regex r, int start) { not r.getAMode() = "MULTILINE" and not r.getAMode() = "VERBOSE" and - r.specialCharacter(start, start+1, "^") and - not r.firstItem(start, start+1) + r.specialCharacter(start, start + 1, "^") and + not r.firstItem(start, start + 1) } from Regex r, int offset where unmatchable_caret(r, offset) -select r, "This regular expression includes an unmatchable caret at offset " + offset.toString() + "." +select r, + "This regular expression includes an unmatchable caret at offset " + offset.toString() + "." diff --git a/python/ql/src/Expressions/Regex/UnmatchableDollar.ql b/python/ql/src/Expressions/Regex/UnmatchableDollar.ql index 49cef2bded1..dfd2bfcf893 100644 --- a/python/ql/src/Expressions/Regex/UnmatchableDollar.ql +++ b/python/ql/src/Expressions/Regex/UnmatchableDollar.ql @@ -16,11 +16,11 @@ import semmle.python.regex predicate unmatchable_dollar(Regex r, int start) { not r.getAMode() = "MULTILINE" and not r.getAMode() = "VERBOSE" and - r.specialCharacter(start, start+1, "$") - and - not r.lastItem(start, start+1) + r.specialCharacter(start, start + 1, "$") and + not r.lastItem(start, start + 1) } from Regex r, int offset where unmatchable_dollar(r, offset) -select r, "This regular expression includes an unmatchable dollar at offset " + offset.toString() + "." +select r, + "This regular expression includes an unmatchable dollar at offset " + offset.toString() + "." diff --git a/python/ql/src/Expressions/TruncatedDivision.ql b/python/ql/src/Expressions/TruncatedDivision.ql index 471b5244de0..399435dbabf 100644 --- a/python/ql/src/Expressions/TruncatedDivision.ql +++ b/python/ql/src/Expressions/TruncatedDivision.ql @@ -1,38 +1,37 @@ - /** - * @name Result of integer division may be truncated - * @description The arguments to a division statement may be integers, which - * may cause the result to be truncated in Python 2. - * @kind problem - * @tags maintainability - * correctness - * @problem.severity warning - * @sub-severity high - * @precision very-high - * @id py/truncated-division - */ +/** + * @name Result of integer division may be truncated + * @description The arguments to a division statement may be integers, which + * may cause the result to be truncated in Python 2. + * @kind problem + * @tags maintainability + * correctness + * @problem.severity warning + * @sub-severity high + * @precision very-high + * @id py/truncated-division + */ import python from BinaryExpr div, ControlFlowNode left, ControlFlowNode right where // Only relevant for Python 2, as all later versions implement true division - major_version() = 2 - and + major_version() = 2 and exists(BinaryExprNode bin, Value lval, Value rval | - bin = div.getAFlowNode() - and bin.getNode().getOp() instanceof Div - and bin.getLeft().pointsTo(lval, left) - and lval.getClass() = ClassValue::int_() - and bin.getRight().pointsTo(rval, right) - and rval.getClass() = ClassValue::int_() + bin = div.getAFlowNode() and + bin.getNode().getOp() instanceof Div and + bin.getLeft().pointsTo(lval, left) and + lval.getClass() = ClassValue::int_() and + bin.getRight().pointsTo(rval, right) and + rval.getClass() = ClassValue::int_() and // Ignore instances where integer division leaves no remainder - and not lval.(NumericValue).getIntValue() % rval.(NumericValue).getIntValue() = 0 - and not bin.getNode().getEnclosingModule().hasFromFuture("division") + not lval.(NumericValue).getIntValue() % rval.(NumericValue).getIntValue() = 0 and + not bin.getNode().getEnclosingModule().hasFromFuture("division") and // Filter out results wrapped in `int(...)` - and not exists(CallNode c | - c = ClassValue::int_().getACall() - and c.getAnArg() = bin + not exists(CallNode c | + c = ClassValue::int_().getACall() and + c.getAnArg() = bin ) ) select div, "Result of division may be truncated as its $@ and $@ arguments may both be integers.", - left.getLocation(), "left", right.getLocation(), "right" + left.getLocation(), "left", right.getLocation(), "right" diff --git a/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql b/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql index 70128406915..8199be8a051 100644 --- a/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql +++ b/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql @@ -22,14 +22,13 @@ predicate string_const(Expr s) { from StrConst s where -// Implicitly concatenated string is in a list and that list contains at least one other string. -exists(List l, Expr other | - not s = other and - l.getAnElt() = s and - l.getAnElt() = other and - string_const(other) -) and -exists(s.getAnImplicitlyConcatenatedPart()) and -not s.isParenthesized() - + // Implicitly concatenated string is in a list and that list contains at least one other string. + exists(List l, Expr other | + not s = other and + l.getAnElt() = s and + l.getAnElt() = other and + string_const(other) + ) and + exists(s.getAnImplicitlyConcatenatedPart()) and + not s.isParenthesized() select s, "Implicit string concatenation. Maybe missing a comma?" diff --git a/python/ql/src/Expressions/UnnecessaryLambda.ql b/python/ql/src/Expressions/UnnecessaryLambda.ql index 2d7bbf72682..2b927973015 100644 --- a/python/ql/src/Expressions/UnnecessaryLambda.ql +++ b/python/ql/src/Expressions/UnnecessaryLambda.ql @@ -15,43 +15,47 @@ import python /* f consists of a single return statement, whose value is a call. The arguments of the call are exactly the parameters of f */ predicate simple_wrapper(Lambda l, Expr wrapped) { exists(Function f, Call c | f = l.getInnerScope() and c = l.getExpression() | - wrapped = c.getFunc() and - count(f.getAnArg()) = count(c.getAnArg()) and - forall(int arg | exists(f.getArg(arg)) | - f.getArgName(arg) = ((Name)c.getArg(arg)).getId()) and - /* Either no **kwargs or they must match */ - (not exists(f.getKwarg()) and not exists(c.getKwargs()) or - ((Name)f.getKwarg()).getId() = ((Name)c.getKwargs()).getId()) and - /* Either no *args or they must match */ - (not exists(f.getVararg()) and not exists(c.getStarargs()) or - ((Name)f.getVararg()).getId() = ((Name)c.getStarargs()).getId()) and - /* No named parameters in call */ - not exists(c.getAKeyword()) - ) - and + wrapped = c.getFunc() and + count(f.getAnArg()) = count(c.getAnArg()) and + forall(int arg | exists(f.getArg(arg)) | f.getArgName(arg) = c.getArg(arg).(Name).getId()) and + /* Either no **kwargs or they must match */ + ( + not exists(f.getKwarg()) and not exists(c.getKwargs()) + or + f.getKwarg().(Name).getId() = c.getKwargs().(Name).getId() + ) and + /* Either no *args or they must match */ + ( + not exists(f.getVararg()) and not exists(c.getStarargs()) + or + f.getVararg().(Name).getId() = c.getStarargs().(Name).getId() + ) and + /* No named parameters in call */ + not exists(c.getAKeyword()) + ) and // f is not necessarily a drop-in replacement for the lambda if there are default argument values not exists(l.getArgs().getADefault()) } /* The expression called will refer to the same object if evaluated when the lambda is created or when the lambda is executed. */ predicate unnecessary_lambda(Lambda l, Expr e) { - simple_wrapper(l, e) and + simple_wrapper(l, e) and ( - /* plain class */ - exists(ClassValue c | e.pointsTo(c)) - or - /* plain function */ - exists(FunctionValue f | e.pointsTo(f)) - or - /* bound-method of enclosing instance */ - exists(ClassValue cls, Attribute a | - cls.getScope() = l.getScope().getScope() and a = e | - ((Name)a.getObject()).getId() = "self" and - cls.hasAttribute(a.getName()) - ) + /* plain class */ + exists(ClassValue c | e.pointsTo(c)) + or + /* plain function */ + exists(FunctionValue f | e.pointsTo(f)) + or + /* bound-method of enclosing instance */ + exists(ClassValue cls, Attribute a | cls.getScope() = l.getScope().getScope() and a = e | + a.getObject().(Name).getId() = "self" and + cls.hasAttribute(a.getName()) + ) ) } from Lambda l, Expr e where unnecessary_lambda(l, e) -select l, "This 'lambda' is just a simple wrapper around a callable object. Use that object directly." \ No newline at end of file +select l, + "This 'lambda' is just a simple wrapper around a callable object. Use that object directly." diff --git a/python/ql/src/Expressions/WrongNameForArgumentInCall.ql b/python/ql/src/Expressions/WrongNameForArgumentInCall.ql index 6abab859f5f..4800f898c54 100644 --- a/python/ql/src/Expressions/WrongNameForArgumentInCall.ql +++ b/python/ql/src/Expressions/WrongNameForArgumentInCall.ql @@ -16,11 +16,12 @@ import python import Expressions.CallArgs - from Call call, FunctionObject func, string name where -illegally_named_parameter_objectapi(call, func, name) and -not func.isAbstract() and -not exists(FunctionObject overridden | func.overrides(overridden) and overridden.getFunction().getAnArg().(Name).getId() = name) -select -call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", func, func.descriptiveString() + illegally_named_parameter_objectapi(call, func, name) and + not func.isAbstract() and + not exists(FunctionObject overridden | + func.overrides(overridden) and overridden.getFunction().getAnArg().(Name).getId() = name + ) +select call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", func, + func.descriptiveString() diff --git a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql index 71d5bec2fca..39d265fe290 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql @@ -18,29 +18,30 @@ import semmle.python.strings predicate string_format(BinaryExpr operation, StrConst str, Value args, AstNode origin) { operation.getOp() instanceof Mod and exists(Value fmt, Context ctx | - operation.getLeft().pointsTo(ctx, fmt, str) and - operation.getRight().pointsTo(ctx, args, origin) + operation.getLeft().pointsTo(ctx, fmt, str) and + operation.getRight().pointsTo(ctx, args, origin) ) } int sequence_length(Value args) { /* Guess length of sequence */ - exists(Tuple seq, AstNode origin | - seq.pointsTo(args,origin) | + exists(Tuple seq, AstNode origin | seq.pointsTo(args, origin) | result = strictcount(seq.getAnElt()) and not seq.getAnElt() instanceof Starred ) or - exists(ImmutableLiteral i | - i.getLiteralValue() = args | - result = 1 - ) + exists(ImmutableLiteral i | i.getLiteralValue() = args | result = 1) } - -from BinaryExpr operation, StrConst fmt, Value args, int slen, int alen, AstNode origin, string provided -where string_format(operation, fmt, args, origin) and slen = sequence_length(args) and alen = format_items(fmt) and slen != alen and -(if slen = 1 then provided = " is provided." else provided = " are provided.") -select operation, "Wrong number of $@ for string format. Format $@ takes " + alen.toString() + ", but " + slen.toString() + provided, - origin, "arguments", - fmt, fmt.getText() +from + BinaryExpr operation, StrConst fmt, Value args, int slen, int alen, AstNode origin, + string provided +where + string_format(operation, fmt, args, origin) and + slen = sequence_length(args) and + alen = format_items(fmt) and + slen != alen and + (if slen = 1 then provided = " is provided." else provided = " are provided.") +select operation, + "Wrong number of $@ for string format. Format $@ takes " + alen.toString() + ", but " + + slen.toString() + provided, origin, "arguments", fmt, fmt.getText() diff --git a/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql b/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql index 9f636213a34..732cb7a8b7e 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql @@ -16,15 +16,20 @@ import CallArgs from Call call, FunctionObject func, string too, string should, int limit where -( - too_many_args_objectapi(call, func, limit) and too = "too many arguments" and should = "no more than " - or - too_few_args_objectapi(call, func, limit) and too = "too few arguments" and should = "no fewer than " -) and -not func.isAbstract() and -not exists(FunctionObject overridden | func.overrides(overridden) and correct_args_if_called_as_method_objectapi(call, overridden)) -/* The semantics of `__new__` can be a bit subtle, so we simply exclude `__new__` methods */ -and not func.getName() = "__new__" - -select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", func, func.descriptiveString() - + ( + too_many_args_objectapi(call, func, limit) and + too = "too many arguments" and + should = "no more than " + or + too_few_args_objectapi(call, func, limit) and + too = "too few arguments" and + should = "no fewer than " + ) and + not func.isAbstract() and + not exists(FunctionObject overridden | + func.overrides(overridden) and correct_args_if_called_as_method_objectapi(call, overridden) + ) and + /* The semantics of `__new__` can be a bit subtle, so we simply exclude `__new__` methods */ + not func.getName() = "__new__" +select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", func, + func.descriptiveString() diff --git a/python/ql/src/Filters/ClassifyFiles.ql b/python/ql/src/Filters/ClassifyFiles.ql index 4448d993903..20062f0451f 100644 --- a/python/ql/src/Filters/ClassifyFiles.ql +++ b/python/ql/src/Filters/ClassifyFiles.ql @@ -11,8 +11,9 @@ import semmle.python.filters.GeneratedCode import semmle.python.filters.Tests predicate classify(File f, string tag) { - f instanceof GeneratedFile and tag = "generated" or - exists (TestScope t | t.getLocation().getFile() = f) and tag = "test" + f instanceof GeneratedFile and tag = "generated" + or + exists(TestScope t | t.getLocation().getFile() = f) and tag = "test" } from File f, string tag diff --git a/python/ql/src/Filters/NotGenerated.ql b/python/ql/src/Filters/NotGenerated.ql index c59368eb9d8..e1efbfd42e3 100644 --- a/python/ql/src/Filters/NotGenerated.ql +++ b/python/ql/src/Filters/NotGenerated.ql @@ -4,6 +4,7 @@ * @kind problem * @id py/not-generated-file-filter */ + import python import external.DefectFilter import semmle.python.filters.GeneratedCode diff --git a/python/ql/src/Filters/NotTest.ql b/python/ql/src/Filters/NotTest.ql index ddea7fd212b..56650e4ff15 100644 --- a/python/ql/src/Filters/NotTest.ql +++ b/python/ql/src/Filters/NotTest.ql @@ -4,6 +4,7 @@ * @kind problem * @id py/not-test-file-filter */ + import python import external.DefectFilter import semmle.python.filters.Tests diff --git a/python/ql/src/Functions/ConsistentReturns.ql b/python/ql/src/Functions/ConsistentReturns.ql index f3344bd8f74..9e28dee36a3 100644 --- a/python/ql/src/Functions/ConsistentReturns.ql +++ b/python/ql/src/Functions/ConsistentReturns.ql @@ -13,20 +13,21 @@ import python predicate explicitly_returns_non_none(Function func) { - exists(Return return | return.getScope() = func and - exists(Expr val | - val= return.getValue() | - not val instanceof None - ) + exists(Return return | + return.getScope() = func and + exists(Expr val | val = return.getValue() | not val instanceof None) ) } predicate has_implicit_return(Function func) { - exists(ControlFlowNode fallthru | fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable()) or + exists(ControlFlowNode fallthru | + fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable() + ) + or exists(Return return | return.getScope() = func and not exists(return.getValue())) } - from Function func where explicitly_returns_non_none(func) and has_implicit_return(func) -select func, "Mixing implicit and explicit returns may indicate an error as implicit returns always return None." +select func, + "Mixing implicit and explicit returns may indicate an error as implicit returns always return None." diff --git a/python/ql/src/Functions/DeprecatedSliceMethod.ql b/python/ql/src/Functions/DeprecatedSliceMethod.ql index ff2df9919a6..c37f2195b54 100644 --- a/python/ql/src/Functions/DeprecatedSliceMethod.ql +++ b/python/ql/src/Functions/DeprecatedSliceMethod.ql @@ -12,13 +12,13 @@ import python predicate slice_method_name(string name) { - name = "__getslice__" or name = "__setslice__" or name = "__delslice__" + name = "__getslice__" or name = "__setslice__" or name = "__delslice__" } from PythonFunctionValue f, string meth - -where f.getScope().isMethod() and not f.isOverridingMethod() and - slice_method_name(meth) and f.getName() = meth - - -select f, meth + " method has been deprecated since Python 2.0" \ No newline at end of file +where + f.getScope().isMethod() and + not f.isOverridingMethod() and + slice_method_name(meth) and + f.getName() = meth +select f, meth + " method has been deprecated since Python 2.0" diff --git a/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql b/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql index c1e497ac470..c9368173a76 100644 --- a/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql +++ b/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql @@ -22,44 +22,87 @@ private predicate indexing_method(string name) { } private predicate arithmetic_method(string name) { - name = "__add__" or name = "__sub__" or name = "__div__" or - name = "__pos__" or name = "__abs__" or name = "__floordiv__" or - name = "__div__" or name = "__divmod__" or name = "__lshift__" or - name = "__and__" or name = "__or__"or name = "__xor__" or name = "__rshift__" or - name = "__pow__" or name = "__mul__" or name = "__neg__" or - name = "__radd__" or name = "__rsub__" or name = "__rdiv__" or - name = "__rfloordiv__" or name = "__rdiv__" or name = "__rlshift__" or - name = "__rand__" or name = "__ror__"or name = "__rxor__" or name = "__rrshift__" or - name = "__rpow__" or name = "__rmul__" or name = "__truediv__" or name = "__rtruediv__" or - name = "__iadd__" or name = "__isub__" or name = "__idiv__" or - name = "__ifloordiv__" or name = "__idiv__" or name = "__ilshift__" or - name = "__iand__" or name = "__ior__"or name = "__ixor__" or name = "__irshift__" or - name = "__ipow__" or name = "__imul__" or name = "__itruediv__" + name = "__add__" or + name = "__sub__" or + name = "__div__" or + name = "__pos__" or + name = "__abs__" or + name = "__floordiv__" or + name = "__div__" or + name = "__divmod__" or + name = "__lshift__" or + name = "__and__" or + name = "__or__" or + name = "__xor__" or + name = "__rshift__" or + name = "__pow__" or + name = "__mul__" or + name = "__neg__" or + name = "__radd__" or + name = "__rsub__" or + name = "__rdiv__" or + name = "__rfloordiv__" or + name = "__rdiv__" or + name = "__rlshift__" or + name = "__rand__" or + name = "__ror__" or + name = "__rxor__" or + name = "__rrshift__" or + name = "__rpow__" or + name = "__rmul__" or + name = "__truediv__" or + name = "__rtruediv__" or + name = "__iadd__" or + name = "__isub__" or + name = "__idiv__" or + name = "__ifloordiv__" or + name = "__idiv__" or + name = "__ilshift__" or + name = "__iand__" or + name = "__ior__" or + name = "__ixor__" or + name = "__irshift__" or + name = "__ipow__" or + name = "__imul__" or + name = "__itruediv__" } private predicate ordering_method(string name) { - name = "__lt__" or name = "__le__" or name = "__gt__" or name = "__ge__" or + name = "__lt__" + or + name = "__le__" + or + name = "__gt__" + or + name = "__ge__" + or name = "__cmp__" and major_version() = 2 } private predicate cast_method(string name) { - name = "__nonzero__" and major_version() = 2 or - name = "__bool__" or - name = "__int__" or name = "__float__" or - name = "__long__" or - name = "__trunc__" or + name = "__nonzero__" and major_version() = 2 + or + name = "__bool__" + or + name = "__int__" + or + name = "__float__" + or + name = "__long__" + or + name = "__trunc__" + or name = "__complex__" } predicate correct_raise(string name, ClassObject ex) { - ex.getAnImproperSuperType() = theTypeErrorType() - and + ex.getAnImproperSuperType() = theTypeErrorType() and ( - name = "__copy__" or - name = "__deepcopy__" or - name = "__call__" or - indexing_method(name) or - attribute_method(name) + name = "__copy__" or + name = "__deepcopy__" or + name = "__call__" or + indexing_method(name) or + attribute_method(name) ) or preferred_raise(name, ex) @@ -84,11 +127,11 @@ predicate no_need_to_raise(string name, string message) { } predicate is_abstract(FunctionObject func) { - ((Name)func.getFunction().getADecorator()).getId().matches("%abstract%") + func.getFunction().getADecorator().(Name).getId().matches("%abstract%") } predicate always_raises(FunctionObject f, ClassObject ex) { - ex = f.getARaisedType() and + ex = f.getARaisedType() and strictcount(f.getARaisedType()) = 1 and not exists(f.getFunction().getANormalExit()) and /* raising StopIteration is equivalent to a return in a generator */ @@ -96,17 +139,17 @@ predicate always_raises(FunctionObject f, ClassObject ex) { } from FunctionObject f, ClassObject cls, string message -where f.getFunction().isSpecialMethod() and -not is_abstract(f) and -always_raises(f, cls) and -( - no_need_to_raise(f.getName(), message) and not cls.getName() = "NotImplementedError" - or - not correct_raise(f.getName(), cls) and not cls.getName() = "NotImplementedError" - and - exists(ClassObject preferred | - preferred_raise(f.getName(), preferred) | - message = "raise " + preferred.getName() + " instead" +where + f.getFunction().isSpecialMethod() and + not is_abstract(f) and + always_raises(f, cls) and + ( + no_need_to_raise(f.getName(), message) and not cls.getName() = "NotImplementedError" + or + not correct_raise(f.getName(), cls) and + not cls.getName() = "NotImplementedError" and + exists(ClassObject preferred | preferred_raise(f.getName(), preferred) | + message = "raise " + preferred.getName() + " instead" + ) ) -) select f, "Function always raises $@; " + message, cls, cls.toString() diff --git a/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql b/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql index a425079cce0..53d70815ddd 100644 --- a/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql +++ b/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql @@ -14,14 +14,18 @@ import Expressions.CallArgs from Call call, FunctionObject func, FunctionObject overridden, string problem where -func.overrides(overridden) and ( - wrong_args_objectapi(call, func, _, problem) and correct_args_if_called_as_method_objectapi(call, overridden) - or - exists(string name | - illegally_named_parameter_objectapi(call, func, name) and problem = "an argument named '" + name + "'" and - overridden.getFunction().getAnArg().(Name).getId() = name + func.overrides(overridden) and + ( + wrong_args_objectapi(call, func, _, problem) and + correct_args_if_called_as_method_objectapi(call, overridden) + or + exists(string name | + illegally_named_parameter_objectapi(call, func, name) and + problem = "an argument named '" + name + "'" and + overridden.getFunction().getAnArg().(Name).getId() = name + ) ) -) - -select func, "Overriding method signature does not match $@, where it is passed " + problem + ". Overridden method $@ is correctly specified.", -call, "here", overridden, overridden.descriptiveString() +select func, + "Overriding method signature does not match $@, where it is passed " + problem + + ". Overridden method $@ is correctly specified.", call, "here", overridden, + overridden.descriptiveString() diff --git a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql index 9636c7c22db..0dd0fd5856b 100644 --- a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql +++ b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql @@ -15,21 +15,23 @@ import Expressions.CallArgs from Call call, FunctionObject func, FunctionObject overriding, string problem where -not func.getName() = "__init__" and -overriding.overrides(func) and -call = overriding.getAMethodCall().getNode() and -correct_args_if_called_as_method_objectapi(call, overriding) and -( - arg_count_objectapi(call)+1 < func.minParameters() and problem = "too few arguments" - or - arg_count_objectapi(call) >= func.maxParameters() and problem = "too many arguments" - or - exists(string name | call.getAKeyword().getArg() = name and - overriding.getFunction().getAnArg().(Name).getId() = name and - not func.getFunction().getAnArg().(Name).getId() = name and - problem = "an argument named '" + name + "'" + not func.getName() = "__init__" and + overriding.overrides(func) and + call = overriding.getAMethodCall().getNode() and + correct_args_if_called_as_method_objectapi(call, overriding) and + ( + arg_count_objectapi(call) + 1 < func.minParameters() and problem = "too few arguments" + or + arg_count_objectapi(call) >= func.maxParameters() and problem = "too many arguments" + or + exists(string name | + call.getAKeyword().getArg() = name and + overriding.getFunction().getAnArg().(Name).getId() = name and + not func.getFunction().getAnArg().(Name).getId() = name and + problem = "an argument named '" + name + "'" + ) ) -) - -select func, "Overridden method signature does not match $@, where it is passed " + problem + ". Overriding method $@ matches the call.", -call, "call", overriding, overriding.descriptiveString() +select func, + "Overridden method signature does not match $@, where it is passed " + problem + + ". Overriding method $@ matches the call.", call, "call", overriding, + overriding.descriptiveString() diff --git a/python/ql/src/Functions/InitIsGenerator.ql b/python/ql/src/Functions/InitIsGenerator.ql index 5ad61ae8255..bb02f103ea3 100644 --- a/python/ql/src/Functions/InitIsGenerator.ql +++ b/python/ql/src/Functions/InitIsGenerator.ql @@ -13,6 +13,7 @@ import python from Function f -where f.isInitMethod() and -(exists(Yield y | y.getScope() = f) or exists(YieldFrom y| y.getScope() = f)) +where + f.isInitMethod() and + (exists(Yield y | y.getScope() = f) or exists(YieldFrom y | y.getScope() = f)) select f, "__init__ method is a generator." diff --git a/python/ql/src/Functions/IterReturnsNonSelf.ql b/python/ql/src/Functions/IterReturnsNonSelf.ql index 0899cf798a1..7ca63493015 100644 --- a/python/ql/src/Functions/IterReturnsNonSelf.ql +++ b/python/ql/src/Functions/IterReturnsNonSelf.ql @@ -13,21 +13,20 @@ import python Function iter_method(ClassObject t) { - result = ((FunctionObject)t.lookupAttribute("__iter__")).getFunction() + result = t.lookupAttribute("__iter__").(FunctionObject).getFunction() } -predicate is_self(Name value, Function f) { - value.getVariable() = ((Name)f.getArg(0)).getVariable() -} +predicate is_self(Name value, Function f) { value.getVariable() = f.getArg(0).(Name).getVariable() } predicate returns_non_self(Function f) { - exists(f.getFallthroughNode()) - or - exists(Return r | r.getScope() = f and not is_self(r.getValue(), f)) - or - exists(Return r | r.getScope() = f and not exists(r.getValue())) + exists(f.getFallthroughNode()) + or + exists(Return r | r.getScope() = f and not is_self(r.getValue(), f)) + or + exists(Return r | r.getScope() = f and not exists(r.getValue())) } from ClassObject t, Function iter where t.isIterator() and iter = iter_method(t) and returns_non_self(iter) -select t, "Class " + t.getName() + " is an iterator but its $@ method does not return 'self'.", iter, iter.getName() \ No newline at end of file +select t, "Class " + t.getName() + " is an iterator but its $@ method does not return 'self'.", + iter, iter.getName() diff --git a/python/ql/src/Functions/NonCls.ql b/python/ql/src/Functions/NonCls.ql index 983a5c75b30..10ca06af12c 100644 --- a/python/ql/src/Functions/NonCls.ql +++ b/python/ql/src/Functions/NonCls.ql @@ -40,9 +40,11 @@ where ( if exists(f.getArgName(0)) then - message = "Class methods or methods of a type deriving from type should have 'cls', rather than '" - + f.getArgName(0) + "', as their first parameter." + message = + "Class methods or methods of a type deriving from type should have 'cls', rather than '" + + f.getArgName(0) + "', as their first parameter." else - message = "Class methods or methods of a type deriving from type should have 'cls' as their first parameter." + message = + "Class methods or methods of a type deriving from type should have 'cls' as their first parameter." ) select f, message diff --git a/python/ql/src/Functions/NonSelf.ql b/python/ql/src/Functions/NonSelf.ql index 2f0cf44ca2a..a3102eee2aa 100644 --- a/python/ql/src/Functions/NonSelf.ql +++ b/python/ql/src/Functions/NonSelf.ql @@ -45,10 +45,12 @@ where ( if exists(f.getArgName(0)) then - message = "Normal methods should have 'self', rather than '" + f.getArgName(0) + + message = + "Normal methods should have 'self', rather than '" + f.getArgName(0) + "', as their first parameter." else - message = "Normal methods should have at least one parameter (the first of which should be 'self')." + message = + "Normal methods should have at least one parameter (the first of which should be 'self')." ) and not f.hasVarArg() ) and diff --git a/python/ql/src/Functions/OverlyComplexDelMethod.ql b/python/ql/src/Functions/OverlyComplexDelMethod.ql index fff4b3fad0b..2503f7ac6a7 100644 --- a/python/ql/src/Functions/OverlyComplexDelMethod.ql +++ b/python/ql/src/Functions/OverlyComplexDelMethod.ql @@ -16,6 +16,9 @@ import python from FunctionObject method -where exists(ClassObject c | c.declaredAttribute("__del__") = method and -method.getFunction().getMetrics().getCyclomaticComplexity() > 3) +where + exists(ClassObject c | + c.declaredAttribute("__del__") = method and + method.getFunction().getMetrics().getCyclomaticComplexity() > 3 + ) select method, "Overly complex '__del__' method." diff --git a/python/ql/src/Functions/ReturnConsistentTupleSizes.ql b/python/ql/src/Functions/ReturnConsistentTupleSizes.ql index 9a39e363872..02965c2a3a5 100644 --- a/python/ql/src/Functions/ReturnConsistentTupleSizes.ql +++ b/python/ql/src/Functions/ReturnConsistentTupleSizes.ql @@ -15,15 +15,16 @@ import python predicate returns_tuple_of_size(Function func, int size, AstNode origin) { exists(Return return, TupleValue val | return.getScope() = func and - return.getValue().pointsTo(val, origin) | + return.getValue().pointsTo(val, origin) + | size = val.length() ) } - from Function func, int s1, int s2, AstNode t1, AstNode t2 where returns_tuple_of_size(func, s1, t1) and returns_tuple_of_size(func, s2, t2) and s1 < s2 -select func, func.getQualifiedName() + " returns $@ and $@.", t1, "tuple of size " + s1, t2, "tuple of size " + s2 +select func, func.getQualifiedName() + " returns $@ and $@.", t1, "tuple of size " + s1, t2, + "tuple of size " + s2 diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index 19896533a7c..4235ef9a5d0 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -21,28 +21,34 @@ predicate meaningful_return_value(Expr val) { or val instanceof BooleanLiteral or - exists(FunctionObject callee | val = callee.getACall().getNode() and returns_meaningful_value(callee)) + exists(FunctionObject callee | + val = callee.getACall().getNode() and returns_meaningful_value(callee) + ) or not exists(FunctionObject callee | val = callee.getACall().getNode()) and not val instanceof Name } /* Value is used before returning, and thus its value is not lost if ignored */ predicate used_value(Expr val) { - exists(LocalVariable var, Expr other | var.getAnAccess() = val and other = var.getAnAccess() and not other = val) + exists(LocalVariable var, Expr other | + var.getAnAccess() = val and other = var.getAnAccess() and not other = val + ) } -predicate returns_meaningful_value(FunctionObject f) { - not exists(f.getFunction().getFallthroughNode()) - and +predicate returns_meaningful_value(FunctionObject f) { + not exists(f.getFunction().getFallthroughNode()) and ( - exists(Return ret, Expr val | ret.getScope() = f.getFunction() and val = ret.getValue() | - meaningful_return_value(val) and - not used_value(val) - ) - or - /* Is f a builtin function that returns something other than None? - * Ignore __import__ as it is often called purely for side effects */ - f.isC() and f.getAnInferredReturnType() != theNoneType() and not f.getName() = "__import__" + exists(Return ret, Expr val | ret.getScope() = f.getFunction() and val = ret.getValue() | + meaningful_return_value(val) and + not used_value(val) + ) + or + /* + * Is f a builtin function that returns something other than None? + * Ignore __import__ as it is often called purely for side effects + */ + + f.isC() and f.getAnInferredReturnType() != theNoneType() and not f.getName() = "__import__" ) } @@ -56,17 +62,19 @@ predicate wrapped_in_try_except(ExprStmt call) { } from ExprStmt call, FunctionObject callee, float percentage_used, int total -where call.getValue() = callee.getACall().getNode() and returns_meaningful_value(callee) and -not wrapped_in_try_except(call) and -exists(int unused | - unused = count(ExprStmt e | e.getValue().getAFlowNode() = callee.getACall()) and - total = count(callee.getACall()) | - percentage_used = (100.0*(total-unused)/total).floor() -) and -/* Report an alert if we see at least 5 calls and the return value is used in at least 3/4 of those calls. */ -percentage_used >= 75 and -total >= 5 - -select call, "Call discards return value of function $@. The result is used in " + percentage_used.toString() + "% of calls.", -callee, callee.getName() - +where + call.getValue() = callee.getACall().getNode() and + returns_meaningful_value(callee) and + not wrapped_in_try_except(call) and + exists(int unused | + unused = count(ExprStmt e | e.getValue().getAFlowNode() = callee.getACall()) and + total = count(callee.getACall()) + | + percentage_used = (100.0 * (total - unused) / total).floor() + ) and + /* Report an alert if we see at least 5 calls and the return value is used in at least 3/4 of those calls. */ + percentage_used >= 75 and + total >= 5 +select call, + "Call discards return value of function $@. The result is used in " + percentage_used.toString() + + "% of calls.", callee, callee.getName() diff --git a/python/ql/src/Functions/SignatureOverriddenMethod.ql b/python/ql/src/Functions/SignatureOverriddenMethod.ql index 47182d8d87d..f79b4e9722c 100644 --- a/python/ql/src/Functions/SignatureOverriddenMethod.ql +++ b/python/ql/src/Functions/SignatureOverriddenMethod.ql @@ -6,7 +6,6 @@ * @problem.severity warning * @tags reliability * correctness - * @problem.severity warning * @sub-severity high * @precision very-high * @id py/inheritance/signature-mismatch @@ -17,19 +16,20 @@ import Expressions.CallArgs from FunctionObject base, PyFunctionObject derived where - not exists(base.getACall()) and - not exists(FunctionObject a_derived | - a_derived.overrides(base) and - exists(a_derived.getACall()) - ) and - not derived.getFunction().isSpecialMethod() and - derived.getName() != "__init__" and - derived.isNormalMethod() and - not derived.getFunction().isSpecialMethod() and - // call to overrides distributed for efficiency - ( - (derived.overrides(base) and derived.minParameters() > base.maxParameters()) - or - (derived.overrides(base) and derived.maxParameters() < base.minParameters()) - ) -select derived, "Overriding method '" + derived.getName() + "' has signature mismatch with $@.", base, "overridden method" + not exists(base.getACall()) and + not exists(FunctionObject a_derived | + a_derived.overrides(base) and + exists(a_derived.getACall()) + ) and + not derived.getFunction().isSpecialMethod() and + derived.getName() != "__init__" and + derived.isNormalMethod() and + not derived.getFunction().isSpecialMethod() and + // call to overrides distributed for efficiency + ( + derived.overrides(base) and derived.minParameters() > base.maxParameters() + or + derived.overrides(base) and derived.maxParameters() < base.minParameters() + ) +select derived, "Overriding method '" + derived.getName() + "' has signature mismatch with $@.", + base, "overridden method" diff --git a/python/ql/src/Functions/SignatureSpecialMethods.ql b/python/ql/src/Functions/SignatureSpecialMethods.ql index 3e718ce2a3b..bd5587ec903 100644 --- a/python/ql/src/Functions/SignatureSpecialMethods.ql +++ b/python/ql/src/Functions/SignatureSpecialMethods.ql @@ -12,105 +12,102 @@ import python - predicate is_unary_op(string name) { - name = "__del__" or - name = "__repr__" or - name = "__str__" or - name = "__hash__" or - name = "__bool__" or - name = "__nonzero__" or - name = "__unicode__" or - name = "__len__" or - name = "__iter__" or - name = "__reversed__" or - name = "__neg__" or - name = "__pos__" or - name = "__abs__" or - name = "__invert__" or - name = "__complex__" or - name = "__int__" or - name = "__float__" or - name = "__long__" or - name = "__oct__" or - name = "__hex__" or - name = "__index__" or - name = "__enter__" + name = "__del__" or + name = "__repr__" or + name = "__str__" or + name = "__hash__" or + name = "__bool__" or + name = "__nonzero__" or + name = "__unicode__" or + name = "__len__" or + name = "__iter__" or + name = "__reversed__" or + name = "__neg__" or + name = "__pos__" or + name = "__abs__" or + name = "__invert__" or + name = "__complex__" or + name = "__int__" or + name = "__float__" or + name = "__long__" or + name = "__oct__" or + name = "__hex__" or + name = "__index__" or + name = "__enter__" } predicate is_binary_op(string name) { - name = "__lt__" or - name = "__le__" or - name = "__eq__" or - name = "__ne__" or - name = "__gt__" or - name = "__ge__" or - name = "__cmp__" or - name = "__rcmp__" or - name = "__getattr___" or - name = "__getattribute___" or - name = "__delattr__" or - name = "__delete__" or - name = "__instancecheck__" or - name = "__subclasscheck__" or - name = "__getitem__" or - name = "__delitem__" or - name = "__contains__" or - name = "__add__" or - name = "__sub__" or - name = "__mul__" or - name = "__floordiv__" or - name = "__div__" or - name = "__truediv__" or - name = "__mod__" or - name = "__divmod__" or - name = "__lshift__" or - name = "__rshift__" or - name = "__and__" or - name = "__xor__" or - name = "__or__" or - name = "__radd__" or - name = "__rsub__" or - name = "__rmul__" or - name = "__rfloordiv__" or - name = "__rdiv__" or - name = "__rtruediv__" or - name = "__rmod__" or - name = "__rdivmod__" or - name = "__rpow__" or - name = "__rlshift__" or - name = "__rrshift__" or - name = "__rand__" or - name = "__rxor__" or - name = "__ror__" or - name = "__iadd__" or - name = "__isub__" or - name = "__imul__" or - name = "__ifloordiv__" or - name = "__idiv__" or - name = "__itruediv__" or - name = "__imod__" or - name = "__idivmod__" or - name = "__ipow__" or - name = "__ilshift__" or - name = "__irshift__" or - name = "__iand__" or - name = "__ixor__" or - name = "__ior__" or - name = "__coerce__" + name = "__lt__" or + name = "__le__" or + name = "__eq__" or + name = "__ne__" or + name = "__gt__" or + name = "__ge__" or + name = "__cmp__" or + name = "__rcmp__" or + name = "__getattr___" or + name = "__getattribute___" or + name = "__delattr__" or + name = "__delete__" or + name = "__instancecheck__" or + name = "__subclasscheck__" or + name = "__getitem__" or + name = "__delitem__" or + name = "__contains__" or + name = "__add__" or + name = "__sub__" or + name = "__mul__" or + name = "__floordiv__" or + name = "__div__" or + name = "__truediv__" or + name = "__mod__" or + name = "__divmod__" or + name = "__lshift__" or + name = "__rshift__" or + name = "__and__" or + name = "__xor__" or + name = "__or__" or + name = "__radd__" or + name = "__rsub__" or + name = "__rmul__" or + name = "__rfloordiv__" or + name = "__rdiv__" or + name = "__rtruediv__" or + name = "__rmod__" or + name = "__rdivmod__" or + name = "__rpow__" or + name = "__rlshift__" or + name = "__rrshift__" or + name = "__rand__" or + name = "__rxor__" or + name = "__ror__" or + name = "__iadd__" or + name = "__isub__" or + name = "__imul__" or + name = "__ifloordiv__" or + name = "__idiv__" or + name = "__itruediv__" or + name = "__imod__" or + name = "__idivmod__" or + name = "__ipow__" or + name = "__ilshift__" or + name = "__irshift__" or + name = "__iand__" or + name = "__ixor__" or + name = "__ior__" or + name = "__coerce__" } predicate is_ternary_op(string name) { - name = "__setattr__" or - name = "__set__" or - name = "__setitem__" or - name = "__getslice__" or - name = "__delslice__" + name = "__setattr__" or + name = "__set__" or + name = "__setitem__" or + name = "__getslice__" or + name = "__delslice__" } -predicate is_quad_op(string name) { - name = "__setslice__" or name = "__exit__" -} +predicate is_quad_op(string name) { name = "__setslice__" or name = "__exit__" } int argument_count(PythonFunctionValue f, string name, ClassValue cls) { cls.declaredAttribute(name) = f and @@ -125,52 +122,62 @@ int argument_count(PythonFunctionValue f, string name, ClassValue cls) { ) } -predicate incorrect_special_method_defn(PythonFunctionValue func, string message, boolean show_counts, string name, ClassValue owner) { - exists(int required | - required = argument_count(func, name, owner) | - /* actual_non_default <= actual */ - if required > func.maxParameters() then - (message = "Too few parameters" and show_counts = true) - else if required < func.minParameters() then - (message = "Too many parameters" and show_counts = true) - else if (func.minParameters() < required and not func.getScope().hasVarArg()) then - (message = (required -func.minParameters()) + " default values(s) will never be used" and show_counts = false) - else - none() - ) +predicate incorrect_special_method_defn( + PythonFunctionValue func, string message, boolean show_counts, string name, ClassValue owner +) { + exists(int required | required = argument_count(func, name, owner) | + /* actual_non_default <= actual */ + if required > func.maxParameters() + then message = "Too few parameters" and show_counts = true + else + if required < func.minParameters() + then message = "Too many parameters" and show_counts = true + else + if func.minParameters() < required and not func.getScope().hasVarArg() + then + message = (required - func.minParameters()) + " default values(s) will never be used" and + show_counts = false + else none() + ) } predicate incorrect_pow(FunctionValue func, string message, boolean show_counts, ClassValue owner) { owner.declaredAttribute("__pow__") = func and ( - func.maxParameters() < 2 and message = "Too few parameters" and show_counts = true - or - func.minParameters() > 3 and message = "Too many parameters" and show_counts = true - or - func.minParameters() < 2 and message = (2 - func.minParameters()) + " default value(s) will never be used" and show_counts = false - or - func.minParameters() = 3 and message = "Third parameter to __pow__ should have a default value" and show_counts = false - ) + func.maxParameters() < 2 and message = "Too few parameters" and show_counts = true + or + func.minParameters() > 3 and message = "Too many parameters" and show_counts = true + or + func.minParameters() < 2 and + message = (2 - func.minParameters()) + " default value(s) will never be used" and + show_counts = false + or + func.minParameters() = 3 and + message = "Third parameter to __pow__ should have a default value" and + show_counts = false + ) } predicate incorrect_get(FunctionValue func, string message, boolean show_counts, ClassValue owner) { owner.declaredAttribute("__get__") = func and ( - func.maxParameters() < 3 and message = "Too few parameters" and show_counts = true - or - func.minParameters() > 3 and message = "Too many parameters" and show_counts = true - or - func.minParameters() < 2 and not func.getScope().hasVarArg() and - message = (2 - func.minParameters()) + " default value(s) will never be used" and show_counts = false - ) + func.maxParameters() < 3 and message = "Too few parameters" and show_counts = true + or + func.minParameters() > 3 and message = "Too many parameters" and show_counts = true + or + func.minParameters() < 2 and + not func.getScope().hasVarArg() and + message = (2 - func.minParameters()) + " default value(s) will never be used" and + show_counts = false + ) } string should_have_parameters(PythonFunctionValue f, string name, ClassValue owner) { - exists(int i | i = argument_count(f, name, owner) | - result = i.toString() - ) - or - owner.declaredAttribute(name) = f and (name = "__get__" or name = "__pow__") and result = "2 or 3" + exists(int i | i = argument_count(f, name, owner) | result = i.toString()) + or + owner.declaredAttribute(name) = f and + (name = "__get__" or name = "__pow__") and + result = "2 or 3" } string has_parameters(PythonFunctionValue f) { @@ -183,18 +190,23 @@ string has_parameters(PythonFunctionValue f) { ) } -from PythonFunctionValue f, string message, string sizes, boolean show_counts, string name, ClassValue owner -where - ( - incorrect_special_method_defn(f, message, show_counts, name, owner) - or - incorrect_pow(f, message, show_counts, owner) and name = "__pow__" - or - incorrect_get(f, message, show_counts, owner) and name = "__get__" - ) - and - ( - show_counts = false and sizes = "" or - show_counts = true and sizes = ", which has " + has_parameters(f) + ", but should have " + should_have_parameters(f, name, owner) - ) +from + PythonFunctionValue f, string message, string sizes, boolean show_counts, string name, + ClassValue owner +where + ( + incorrect_special_method_defn(f, message, show_counts, name, owner) + or + incorrect_pow(f, message, show_counts, owner) and name = "__pow__" + or + incorrect_get(f, message, show_counts, owner) and name = "__get__" + ) and + ( + show_counts = false and sizes = "" + or + show_counts = true and + sizes = + ", which has " + has_parameters(f) + ", but should have " + + should_have_parameters(f, name, owner) + ) select f, message + " for special method " + name + sizes + ", in class $@.", owner, owner.getName() diff --git a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql index ab797844533..38632358c08 100644 --- a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql +++ b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql @@ -13,9 +13,11 @@ import python import Testing.Mox predicate is_used(Call c) { - exists(Expr outer | outer != c and outer.containsInScope(c) | outer instanceof Call or outer instanceof Attribute or outer instanceof Subscript) + exists(Expr outer | outer != c and outer.containsInScope(c) | + outer instanceof Call or outer instanceof Attribute or outer instanceof Subscript + ) or - exists(Stmt s | + exists(Stmt s | c = s.getASubExpression() and not s instanceof ExprStmt and /* Ignore if a single return, as def f(): return g() is quite common. Covers implicit return in a lambda. */ @@ -24,11 +26,13 @@ predicate is_used(Call c) { } from Call c, FunctionValue func -where -/* Call result is used, but callee is a procedure */ -is_used(c) and c.getFunc().pointsTo(func) and func.getScope().isProcedure() and -/* All callees are procedures */ -forall(FunctionValue callee | c.getFunc().pointsTo(callee) | callee.getScope().isProcedure()) and -/* Mox return objects have an `AndReturn` method */ -not useOfMoxInModule(c.getEnclosingModule()) +where + /* Call result is used, but callee is a procedure */ + is_used(c) and + c.getFunc().pointsTo(func) and + func.getScope().isProcedure() and + /* All callees are procedures */ + forall(FunctionValue callee | c.getFunc().pointsTo(callee) | callee.getScope().isProcedure()) and + /* Mox return objects have an `AndReturn` method */ + not useOfMoxInModule(c.getEnclosingModule()) select c, "The result of '$@' is used even though it is always None.", func, func.getQualifiedName() diff --git a/python/ql/src/Imports/DeprecatedModule.ql b/python/ql/src/Imports/DeprecatedModule.ql index 5ecd7f45cfe..359f3dad10d 100644 --- a/python/ql/src/Imports/DeprecatedModule.ql +++ b/python/ql/src/Imports/DeprecatedModule.ql @@ -60,7 +60,8 @@ predicate deprecated_module(string name, string instead, int major, int minor) { string deprecation_message(string mod) { exists(int major, int minor | deprecated_module(mod, _, major, minor) | - result = "The " + mod + " module was deprecated in version " + major.toString() + "." + + result = + "The " + mod + " module was deprecated in version " + major.toString() + "." + minor.toString() + "." ) } @@ -77,8 +78,7 @@ from ImportExpr imp, string name, string instead where name = imp.getName() and deprecated_module(name, instead, _, _) and - not exists(Try try, ExceptStmt except | except = try.getAHandler() - | + not exists(Try try, ExceptStmt except | except = try.getAHandler() | except.getType().pointsTo(ClassValue::importError()) and except.containsInScope(imp) ) diff --git a/python/ql/src/Imports/EncodingError.ql b/python/ql/src/Imports/EncodingError.ql index f26bf8dad33..962ae4426df 100644 --- a/python/ql/src/Imports/EncodingError.ql +++ b/python/ql/src/Imports/EncodingError.ql @@ -13,4 +13,4 @@ import python from EncodingError error -select error, error.getMessage() \ No newline at end of file +select error, error.getMessage() diff --git a/python/ql/src/Imports/ImportShadowedByLoopVar.ql b/python/ql/src/Imports/ImportShadowedByLoopVar.ql index 29f6536cce7..f3817a1bcde 100644 --- a/python/ql/src/Imports/ImportShadowedByLoopVar.ql +++ b/python/ql/src/Imports/ImportShadowedByLoopVar.ql @@ -13,10 +13,13 @@ import python predicate shadowsImport(Variable l) { - exists(Import i, Name shadow | shadow = i.getAName().getAsname() and shadow.getId() = l.getId() and i.getScope() = l.getScope().getScope*()) + exists(Import i, Name shadow | + shadow = i.getAName().getAsname() and + shadow.getId() = l.getId() and + i.getScope() = l.getScope().getScope*() + ) } - from Variable l, Name defn where shadowsImport(l) and defn.defines(l) and exists(For for | defn = for.getTarget()) select defn, "Loop variable '" + l.getId() + "' shadows an import" diff --git a/python/ql/src/Imports/ImportStarUsed.ql b/python/ql/src/Imports/ImportStarUsed.ql index bc125c05a3b..ad25748e771 100644 --- a/python/ql/src/Imports/ImportStarUsed.ql +++ b/python/ql/src/Imports/ImportStarUsed.ql @@ -14,4 +14,3 @@ import python from ImportStar i select i, "Using 'from ... import *' pollutes the namespace" - diff --git a/python/ql/src/Imports/ImportandImportFrom.ql b/python/ql/src/Imports/ImportandImportFrom.ql index 6a12e6b938d..f04e6d896ba 100644 --- a/python/ql/src/Imports/ImportandImportFrom.ql +++ b/python/ql/src/Imports/ImportandImportFrom.ql @@ -12,9 +12,10 @@ import python predicate import_and_import_from(Import i1, Import i2, Module m) { - i1.getEnclosingModule() = i2.getEnclosingModule() and - exists (ImportExpr e1, ImportExpr e2, ImportMember im | - e1 = i1.getAName().getValue() and im = i2.getAName().getValue() and e2 = im.getModule() | + i1.getEnclosingModule() = i2.getEnclosingModule() and + exists(ImportExpr e1, ImportExpr e2, ImportMember im | + e1 = i1.getAName().getValue() and im = i2.getAName().getValue() and e2 = im.getModule() + | e1.getName() = m.getName() and e2.getName() = m.getName() ) } diff --git a/python/ql/src/Imports/Imports.ql b/python/ql/src/Imports/Imports.ql index 7adba83cfe4..233aa7b68be 100644 --- a/python/ql/src/Imports/Imports.ql +++ b/python/ql/src/Imports/Imports.ql @@ -11,16 +11,15 @@ * @id py/multiple-imports-on-line */ -/* Look for imports of the form: -import modA, modB -(Imports should be one per line according PEP 8) -*/ +/* + * Look for imports of the form: + * import modA, modB + * (Imports should be one per line according PEP 8) + */ import python -predicate multiple_import(Import imp) { - count(imp.getAName()) > 1 and not imp.isFromImport() -} +predicate multiple_import(Import imp) { count(imp.getAName()) > 1 and not imp.isFromImport() } from Import i where multiple_import(i) diff --git a/python/ql/src/Imports/ModuleImportsItself.ql b/python/ql/src/Imports/ModuleImportsItself.ql index 1000842550a..3a4ad487687 100644 --- a/python/ql/src/Imports/ModuleImportsItself.ql +++ b/python/ql/src/Imports/ModuleImportsItself.ql @@ -14,7 +14,8 @@ import python predicate modules_imports_itself(ImportingStmt i, ModuleValue m) { i.getEnclosingModule() = m.getScope() and - m = max(string s, ModuleValue m_ | + m = + max(string s, ModuleValue m_ | s = i.getAnImportedModuleName() and m_.importedAs(s) | diff --git a/python/ql/src/Imports/MultipleImports.ql b/python/ql/src/Imports/MultipleImports.ql index 4e5f16779c0..09638457423 100644 --- a/python/ql/src/Imports/MultipleImports.ql +++ b/python/ql/src/Imports/MultipleImports.ql @@ -12,33 +12,35 @@ import python -predicate is_simple_import(Import imp) { - not exists(Attribute a | imp.contains(a)) -} +predicate is_simple_import(Import imp) { not exists(Attribute a | imp.contains(a)) } predicate double_import(Import original, Import duplicate, Module m) { original != duplicate and - is_simple_import(original) and is_simple_import(duplicate) and + is_simple_import(original) and + is_simple_import(duplicate) and /* Imports import the same thing */ - exists (ImportExpr e1, ImportExpr e2 | e1.getName() = m.getName() and e2.getName() = m.getName() and - e1 = original.getAName().getValue() and e2 = duplicate.getAName().getValue() + exists(ImportExpr e1, ImportExpr e2 | + e1.getName() = m.getName() and + e2.getName() = m.getName() and + e1 = original.getAName().getValue() and + e2 = duplicate.getAName().getValue() ) and - original.getAName().getAsname().(Name).getId() = duplicate.getAName().getAsname().(Name).getId() - and + original.getAName().getAsname().(Name).getId() = duplicate.getAName().getAsname().(Name).getId() and exists(Module enclosing | original.getScope() = enclosing and duplicate.getEnclosingModule() = enclosing and ( - /* Duplicate is not at top level scope */ - duplicate.getScope() != enclosing - or - /* Original dominates duplicate */ - original.getAnEntryNode().dominates(duplicate.getAnEntryNode()) + /* Duplicate is not at top level scope */ + duplicate.getScope() != enclosing + or + /* Original dominates duplicate */ + original.getAnEntryNode().dominates(duplicate.getAnEntryNode()) ) - ) + ) } from Import original, Import duplicate, Module m where double_import(original, duplicate, m) -select duplicate, "This import of module " + m.getName() + " is redundant, as it was previously imported $@.", - original, "on line " + original.getLocation().getStartLine().toString() +select duplicate, + "This import of module " + m.getName() + " is redundant, as it was previously imported $@.", + original, "on line " + original.getLocation().getStartLine().toString() diff --git a/python/ql/src/Imports/SyntaxError.ql b/python/ql/src/Imports/SyntaxError.ql index 8a2e0567a04..fd92211d241 100644 --- a/python/ql/src/Imports/SyntaxError.ql +++ b/python/ql/src/Imports/SyntaxError.ql @@ -14,4 +14,4 @@ import python from SyntaxError error where not error instanceof EncodingError -select error, error.getMessage() + " (in Python " + major_version() + ")." \ No newline at end of file +select error, error.getMessage() + " (in Python " + major_version() + ")." diff --git a/python/ql/src/Imports/UnintentionalImport.ql b/python/ql/src/Imports/UnintentionalImport.ql index 8e396896e95..47ae2c999a5 100644 --- a/python/ql/src/Imports/UnintentionalImport.ql +++ b/python/ql/src/Imports/UnintentionalImport.ql @@ -25,8 +25,8 @@ predicate all_defined(ModuleValue exporter) { exporter.getScope().getInitModule().(ImportTimeScope).definesName("__all__") } - from ImportStar imp, ModuleValue exporter where import_star(imp, exporter) and not all_defined(exporter) -select imp, "Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.", - exporter, exporter.getName() +select imp, + "Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.", + exporter, exporter.getName() diff --git a/python/ql/src/Lexical/CommentedOutCode.ql b/python/ql/src/Lexical/CommentedOutCode.ql index 5b71bd2fe0a..d40ce95598a 100644 --- a/python/ql/src/Lexical/CommentedOutCode.ql +++ b/python/ql/src/Lexical/CommentedOutCode.ql @@ -12,7 +12,6 @@ */ import python - import Lexical.CommentedOutCode from CommentedOutCodeBlock c diff --git a/python/ql/src/Lexical/FCommentedOutCode.ql b/python/ql/src/Lexical/FCommentedOutCode.ql index 2f6ee0741c6..e988f4074c7 100644 --- a/python/ql/src/Lexical/FCommentedOutCode.ql +++ b/python/ql/src/Lexical/FCommentedOutCode.ql @@ -11,10 +11,8 @@ import python import Lexical.CommentedOutCode - import python from File f, int n where n = count(CommentedOutCodeLine c | not c.maybeExampleCode() and c.getLocation().getFile() = f) -select f, n -order by n desc +select f, n order by n desc diff --git a/python/ql/src/Lexical/OldOctalLiteral.ql b/python/ql/src/Lexical/OldOctalLiteral.ql index af0ee723c10..28791d8903d 100644 --- a/python/ql/src/Lexical/OldOctalLiteral.ql +++ b/python/ql/src/Lexical/OldOctalLiteral.ql @@ -12,8 +12,7 @@ import python predicate is_old_octal(IntegerLiteral i) { - exists(string text | - text = i.getText() | + exists(string text | text = i.getText() | text.charAt(0) = "0" and not text = "00" and exists(text.charAt(1).toInt()) and diff --git a/python/ql/src/Metrics/CLinesOfCode.ql b/python/ql/src/Metrics/CLinesOfCode.ql index 5c5453fb76a..c7b29615593 100644 --- a/python/ql/src/Metrics/CLinesOfCode.ql +++ b/python/ql/src/Metrics/CLinesOfCode.ql @@ -8,8 +8,8 @@ * @metricAggregate avg sum max * @tags maintainability */ + import python from Function f -select f, f.getMetrics().getNumberOfLinesOfCode() as n -order by n desc \ No newline at end of file +select f, f.getMetrics().getNumberOfLinesOfCode() as n order by n desc diff --git a/python/ql/src/Metrics/ClassAfferentCoupling.ql b/python/ql/src/Metrics/ClassAfferentCoupling.ql index 5fd2ec4c16f..295e8c61a6c 100644 --- a/python/ql/src/Metrics/ClassAfferentCoupling.ql +++ b/python/ql/src/Metrics/ClassAfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ClassMetrics cls -select cls, cls.getAfferentCoupling() as n -order by n desc - +select cls, cls.getAfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/ClassEfferentCoupling.ql b/python/ql/src/Metrics/ClassEfferentCoupling.ql index d8d9dabd5dd..d960c0142e3 100644 --- a/python/ql/src/Metrics/ClassEfferentCoupling.ql +++ b/python/ql/src/Metrics/ClassEfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ClassMetrics cls -select cls, cls.getEfferentCoupling() as n -order by n desc - +select cls, cls.getEfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/CommentRatio.ql b/python/ql/src/Metrics/CommentRatio.ql index 3f04da28283..76a185321ac 100644 --- a/python/ql/src/Metrics/CommentRatio.ql +++ b/python/ql/src/Metrics/CommentRatio.ql @@ -10,9 +10,10 @@ * @tags maintainability * documentation */ + import python from Module m, ModuleMetrics mm where mm = m.getMetrics() and mm.getNumberOfLines() > 0 -select m, 100.0 * ((float)mm.getNumberOfLinesOfComments() / (float)mm.getNumberOfLines()) as ratio -order by ratio desc +select m, 100.0 * (mm.getNumberOfLinesOfComments().(float) / mm.getNumberOfLines().(float)) as ratio + order by ratio desc diff --git a/python/ql/src/Metrics/CyclomaticComplexity.ql b/python/ql/src/Metrics/CyclomaticComplexity.ql index c5ab9858202..1e332f4ec9f 100644 --- a/python/ql/src/Metrics/CyclomaticComplexity.ql +++ b/python/ql/src/Metrics/CyclomaticComplexity.ql @@ -11,9 +11,9 @@ * complexity * maintainability */ + import python from Function func, int complexity where complexity = func.getMetrics().getCyclomaticComplexity() -select func, complexity -order by complexity desc \ No newline at end of file +select func, complexity order by complexity desc diff --git a/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql index 49506b0a0f9..b2c319070ea 100644 --- a/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -2,7 +2,7 @@ * @name External dependencies * @description Count the number of dependencies that a Python source file has on external packages. * @kind treemap - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType externalDependency * @precision medium * @id py/external-dependencies @@ -11,18 +11,18 @@ import python import semmle.python.dependencies.TechInventory -/* +/* * These two columns encode four logical columns: - * + * * 1. Python source file where the dependency originates * 2. Package Object, ideally referring to a PyPI or similar externally provided package * 3. Version of that package Object, if known * 4. Number of dependencies from the source file to the package - * + * * Ideally this query would therefore return three columns, * but this would require changing the dashboard database schema * and dashboard extractor. - * + * * The first column (the Python source file) is prepended with a '/' * so that the file path matches the path used for the file in the * dashboard database, which is implicitly relative to the source @@ -30,15 +30,15 @@ import semmle.python.dependencies.TechInventory */ predicate src_package_count(File sourceFile, ExternalPackage package, int total) { - total = strictcount(AstNode src | - dependency(src, package) and - src.getLocation().getFile() = sourceFile - ) + total = + strictcount(AstNode src | + dependency(src, package) and + src.getLocation().getFile() = sourceFile + ) } from File sourceFile, int total, string entity, ExternalPackage package -where -src_package_count(sourceFile, package, total) and -entity = munge(sourceFile, package) -select entity, total -order by total desc +where + src_package_count(sourceFile, package, total) and + entity = munge(sourceFile, package) +select entity, total order by total desc diff --git a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index 3129edd6328..2424d82abeb 100644 --- a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -16,11 +16,12 @@ import semmle.python.dependencies.TechInventory * recover that information once we are in the dashboard database, using the * ExternalEntity.getASourceLink() method. */ + from File sourceFile, string entity where - exists(PackageObject package, AstNode src | - dependency(src, package) and - src.getLocation().getFile() = sourceFile and - entity = munge(sourceFile, package) - ) + exists(PackageObject package, AstNode src | + dependency(src, package) and + src.getLocation().getFile() = sourceFile and + entity = munge(sourceFile, package) + ) select entity, sourceFile diff --git a/python/ql/src/Metrics/DirectImports.ql b/python/ql/src/Metrics/DirectImports.ql index ec9114cddd9..240cd65e687 100644 --- a/python/ql/src/Metrics/DirectImports.ql +++ b/python/ql/src/Metrics/DirectImports.ql @@ -9,6 +9,7 @@ * @tags modularity * maintainability */ + import python from ModuleValue m, int n diff --git a/python/ql/src/Metrics/DocStringRatio.ql b/python/ql/src/Metrics/DocStringRatio.ql index 43d8d7af248..46859560c16 100644 --- a/python/ql/src/Metrics/DocStringRatio.ql +++ b/python/ql/src/Metrics/DocStringRatio.ql @@ -9,9 +9,11 @@ * @tags maintainability * documentation */ + import python from Module m, ModuleMetrics mm -where mm = m.getMetrics() and mm.getNumberOfLines() > 0 -select m, 100.0 * ((float)mm.getNumberOfLinesOfDocStrings() / (float)mm.getNumberOfLines()) as ratio -order by ratio desc +where mm = m.getMetrics() and mm.getNumberOfLines() > 0 +select m, + 100.0 * (mm.getNumberOfLinesOfDocStrings().(float) / mm.getNumberOfLines().(float)) as ratio + order by ratio desc diff --git a/python/ql/src/Metrics/External/CommitDisplayStrings.ql b/python/ql/src/Metrics/External/CommitDisplayStrings.ql index dd5104996d0..a682f4d1de6 100644 --- a/python/ql/src/Metrics/External/CommitDisplayStrings.ql +++ b/python/ql/src/Metrics/External/CommitDisplayStrings.ql @@ -4,7 +4,9 @@ * @id py/commit-display-strings * @metricType commit */ + import python import external.VCS + from Commit c select c.getRevisionName(), c.getMessage() + "(" + c.getDate().toString() + ")" diff --git a/python/ql/src/Metrics/External/CommitSourceLinks.ql b/python/ql/src/Metrics/External/CommitSourceLinks.ql index a31b73e2a7c..607829288c6 100644 --- a/python/ql/src/Metrics/External/CommitSourceLinks.ql +++ b/python/ql/src/Metrics/External/CommitSourceLinks.ql @@ -4,8 +4,10 @@ * @id py/commit-source-links * @metricType commit */ + import python import external.VCS + from Commit c, File f where f.fromSource() and f = c.getAnAffectedFile() select c.getRevisionName(), f diff --git a/python/ql/src/Metrics/FClasses.ql b/python/ql/src/Metrics/FClasses.ql index da667bd1df5..4736021caf2 100644 --- a/python/ql/src/Metrics/FClasses.ql +++ b/python/ql/src/Metrics/FClasses.ql @@ -13,5 +13,4 @@ import python from Module m, int n where n = count(Class c | c.getEnclosingModule() = m) -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FFunctionsAndMethods.ql b/python/ql/src/Metrics/FFunctionsAndMethods.ql index b8d3a43b1dd..5b9fdf799cf 100644 --- a/python/ql/src/Metrics/FFunctionsAndMethods.ql +++ b/python/ql/src/Metrics/FFunctionsAndMethods.ql @@ -13,5 +13,4 @@ import python from Module m, int n where n = count(Function f | f.getEnclosingModule() = m and f.getName() != "lambda") -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLines.ql b/python/ql/src/Metrics/FLines.ql index 04d9abad7e4..340fb6f58ea 100644 --- a/python/ql/src/Metrics/FLines.ql +++ b/python/ql/src/Metrics/FLines.ql @@ -7,9 +7,9 @@ * @metricType file * @metricAggregate avg sum max */ + import python from Module m, int n where n = m.getMetrics().getNumberOfLines() -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfCode.ql b/python/ql/src/Metrics/FLinesOfCode.ql index 778897c6ae0..a46698c7087 100644 --- a/python/ql/src/Metrics/FLinesOfCode.ql +++ b/python/ql/src/Metrics/FLinesOfCode.ql @@ -10,9 +10,9 @@ * @tags maintainability * @id py/lines-of-code-in-files */ + import python from Module m, int n where n = m.getMetrics().getNumberOfLinesOfCode() -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfComments.ql b/python/ql/src/Metrics/FLinesOfComments.ql index 38b19c2dc46..bd52f8d5caa 100644 --- a/python/ql/src/Metrics/FLinesOfComments.ql +++ b/python/ql/src/Metrics/FLinesOfComments.ql @@ -9,9 +9,10 @@ * @precision very-high * @id py/lines-of-comments-in-files */ + import python from Module m, int n -where n = m.getMetrics().getNumberOfLinesOfComments() + m.getMetrics().getNumberOfLinesOfDocStrings() -select m, n -order by n desc +where + n = m.getMetrics().getNumberOfLinesOfComments() + m.getMetrics().getNumberOfLinesOfDocStrings() +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql b/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql index ac8e0a3a25c..03bee534ee3 100644 --- a/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql +++ b/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql @@ -10,17 +10,17 @@ * @tags testability * @id py/duplicated-lines-in-files */ + import python import external.CodeDuplication - + from File f, int n - -where n = count(int line | - exists(DuplicateBlock d | d.sourceFile() = f | - line in [d.sourceStartLine()..d.sourceEndLine()] and - not whitelistedLineForDuplication(f, line) - ) -) - -select f, n -order by n desc +where + n = + count(int line | + exists(DuplicateBlock d | d.sourceFile() = f | + line in [d.sourceStartLine() .. d.sourceEndLine()] and + not whitelistedLineForDuplication(f, line) + ) + ) +select f, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfSimilarCode.ql b/python/ql/src/Metrics/FLinesOfSimilarCode.ql index e78fe52959b..d407a38d63d 100644 --- a/python/ql/src/Metrics/FLinesOfSimilarCode.ql +++ b/python/ql/src/Metrics/FLinesOfSimilarCode.ql @@ -10,17 +10,17 @@ * @tags testability * @id py/similar-lines-in-files */ + import python import external.CodeDuplication - + from File f, int n - -where n = count(int line | - exists(SimilarBlock d | d.sourceFile() = f | - line in [d.sourceStartLine()..d.sourceEndLine()] and - not whitelistedLineForDuplication(f, line) - ) -) - -select f, n -order by n desc +where + n = + count(int line | + exists(SimilarBlock d | d.sourceFile() = f | + line in [d.sourceStartLine() .. d.sourceEndLine()] and + not whitelistedLineForDuplication(f, line) + ) + ) +select f, n order by n desc diff --git a/python/ql/src/Metrics/FNumberOfTests.ql b/python/ql/src/Metrics/FNumberOfTests.ql index 1cc914a0d55..34a76c70d33 100644 --- a/python/ql/src/Metrics/FNumberOfTests.ql +++ b/python/ql/src/Metrics/FNumberOfTests.ql @@ -6,13 +6,12 @@ * @metricType file * @metricAggregate avg sum max * @precision medium - * @precision very-high * @id py/tests-in-files */ + import python import semmle.python.filters.Tests from Module m, int n where n = strictcount(Test test | test.getEnclosingModule() = m) -select m.getFile(), n -order by n desc +select m.getFile(), n order by n desc diff --git a/python/ql/src/Metrics/FunctionNumberOfCalls.ql b/python/ql/src/Metrics/FunctionNumberOfCalls.ql index 0dd5050214a..fb4dfe5a9d2 100644 --- a/python/ql/src/Metrics/FunctionNumberOfCalls.ql +++ b/python/ql/src/Metrics/FunctionNumberOfCalls.ql @@ -3,14 +3,12 @@ * @description The total number of calls in a function. * @kind treemap * @id py/number-of-calls-per-function - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType callable * @metricAggregate avg max */ import python - from FunctionMetrics func -select func, func.getNumberOfCalls() as n -order by n desc +select func, func.getNumberOfCalls() as n order by n desc diff --git a/python/ql/src/Metrics/FunctionStatementNestingDepth.ql b/python/ql/src/Metrics/FunctionStatementNestingDepth.ql index 64a72fbd34d..ab40cc6068d 100644 --- a/python/ql/src/Metrics/FunctionStatementNestingDepth.ql +++ b/python/ql/src/Metrics/FunctionStatementNestingDepth.ql @@ -12,7 +12,5 @@ import python - from FunctionMetrics func -select func, func.getStatementNestingDepth() as n -order by n desc +select func, func.getStatementNestingDepth() as n order by n desc diff --git a/python/ql/src/Metrics/History/HChurn.ql b/python/ql/src/Metrics/History/HChurn.ql index 437fae7460c..e18b8dd528a 100644 --- a/python/ql/src/Metrics/History/HChurn.ql +++ b/python/ql/src/Metrics/History/HChurn.ql @@ -7,11 +7,17 @@ * @metricType file * @metricAggregate avg sum max */ + import python import external.VCS from Module m, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentChurnForFile(m.getFile()) and not artificialChange(entry) | churn) - and exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, n -order by n desc +where + n = + sum(Commit entry, int churn | + churn = entry.getRecentChurnForFile(m.getFile()) and not artificialChange(entry) + | + churn + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) +select m, n order by n desc diff --git a/python/ql/src/Metrics/History/HLinesAdded.ql b/python/ql/src/Metrics/History/HLinesAdded.ql index 9eea8687118..239d227f365 100644 --- a/python/ql/src/Metrics/History/HLinesAdded.ql +++ b/python/ql/src/Metrics/History/HLinesAdded.ql @@ -7,11 +7,17 @@ * @metricType file * @metricAggregate avg sum max */ + import python import external.VCS from Module m, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentAdditionsForFile(m.getFile()) and not artificialChange(entry) | churn) - and exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, n -order by n desc +where + n = + sum(Commit entry, int churn | + churn = entry.getRecentAdditionsForFile(m.getFile()) and not artificialChange(entry) + | + churn + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) +select m, n order by n desc diff --git a/python/ql/src/Metrics/History/HLinesDeleted.ql b/python/ql/src/Metrics/History/HLinesDeleted.ql index 905d15b524c..7f02c17cc2c 100644 --- a/python/ql/src/Metrics/History/HLinesDeleted.ql +++ b/python/ql/src/Metrics/History/HLinesDeleted.ql @@ -7,11 +7,17 @@ * @metricType file * @metricAggregate avg sum max */ + import python import external.VCS from Module m, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentDeletionsForFile(m.getFile()) and not artificialChange(entry) | churn) - and exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, n -order by n desc +where + n = + sum(Commit entry, int churn | + churn = entry.getRecentDeletionsForFile(m.getFile()) and not artificialChange(entry) + | + churn + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) +select m, n order by n desc diff --git a/python/ql/src/Metrics/History/HNumberOfAuthors.ql b/python/ql/src/Metrics/History/HNumberOfAuthors.ql index fef769fc705..15e679e58c5 100644 --- a/python/ql/src/Metrics/History/HNumberOfAuthors.ql +++ b/python/ql/src/Metrics/History/HNumberOfAuthors.ql @@ -7,10 +7,10 @@ * @metricType file * @metricAggregate avg min max */ + import python import external.VCS from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) select m, count(Author author | author.getAnEditedFile() = m.getFile()) - diff --git a/python/ql/src/Metrics/History/HNumberOfCoCommits.ql b/python/ql/src/Metrics/History/HNumberOfCoCommits.ql index 81dbe8ba2da..4f48641e394 100644 --- a/python/ql/src/Metrics/History/HNumberOfCoCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfCoCommits.ql @@ -7,14 +7,17 @@ * @metricType file * @metricAggregate avg min max */ + import python import external.VCS -int committedFiles(Commit commit) { - result = count(commit.getAnAffectedFile()) -} +int committedFiles(Commit commit) { result = count(commit.getAnAffectedFile()) } from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, avg(Commit commit, int toAvg | (commit.getAnAffectedFile() = m.getFile()) and (toAvg = committedFiles(commit)-1) | toAvg) - +select m, + avg(Commit commit, int toAvg | + commit.getAnAffectedFile() = m.getFile() and toAvg = committedFiles(commit) - 1 + | + toAvg + ) diff --git a/python/ql/src/Metrics/History/HNumberOfCommits.ql b/python/ql/src/Metrics/History/HNumberOfCommits.ql index deca31e1444..d7f99646fe3 100644 --- a/python/ql/src/Metrics/History/HNumberOfCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfCommits.ql @@ -7,6 +7,7 @@ * @metricType commit * @metricAggregate sum */ + import python import external.VCS diff --git a/python/ql/src/Metrics/History/HNumberOfReCommits.ql b/python/ql/src/Metrics/History/HNumberOfReCommits.ql index f5831944aed..c1863e934c9 100644 --- a/python/ql/src/Metrics/History/HNumberOfReCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfReCommits.ql @@ -5,25 +5,30 @@ * @id py/historical-number-of-re-commits * @treemap.warnOn highValues * @metricType file - * @metricAggregate avg min max + * @metricAggregate avg min max */ + import python import external.VCS predicate inRange(Commit first, Commit second) { - first.getAnAffectedFile() = second.getAnAffectedFile() and - first != second and - exists(int n | n = first.getDate().daysTo(second.getDate()) and - n >= 0 and n < 5) + first.getAnAffectedFile() = second.getAnAffectedFile() and + first != second and + exists(int n | + n = first.getDate().daysTo(second.getDate()) and + n >= 0 and + n < 5 + ) } int recommitsForFile(File f) { - result = count(Commit recommit | - f = recommit.getAnAffectedFile() and - exists(Commit prev | inRange(prev, recommit))) + result = + count(Commit recommit | + f = recommit.getAnAffectedFile() and + exists(Commit prev | inRange(prev, recommit)) + ) } from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) select m, recommitsForFile(m.getFile()) - diff --git a/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql b/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql index 6ea84550f76..75832cc82bd 100644 --- a/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql +++ b/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql @@ -7,10 +7,18 @@ * @metricType file * @metricAggregate avg min max */ + import python import external.VCS from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, count(Author author | exists(Commit e | e = author.getACommit() and m.getFile() = e.getAnAffectedFile() and e.daysToNow() <= 180 and not artificialChange(e))) - +select m, + count(Author author | + exists(Commit e | + e = author.getACommit() and + m.getFile() = e.getAnAffectedFile() and + e.daysToNow() <= 180 and + not artificialChange(e) + ) + ) diff --git a/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql b/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql index 3f35a9cba77..9b90a73294f 100644 --- a/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql +++ b/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql @@ -5,13 +5,16 @@ * @id py/historical-number-of-recent-changed-files * @treemap.warnOn highValues * @metricType file - * @metricAggregate avg min max + * @metricAggregate avg min max */ + import python import external.VCS from Module m -where exists(Commit e | e.getAnAffectedFile() = m.getFile() and e.daysToNow() <= 180 and not artificialChange(e)) - and exists(m.getMetrics().getNumberOfLinesOfCode()) +where + exists(Commit e | + e.getAnAffectedFile() = m.getFile() and e.daysToNow() <= 180 and not artificialChange(e) + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) select m, 1 - diff --git a/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql b/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql index e9e3b14538f..7ebec9bb7a4 100644 --- a/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql @@ -7,10 +7,10 @@ * @metricType commit * @metricAggregate sum */ + import python import external.VCS from Commit c where c.daysToNow() <= 180 and not artificialChange(c) select c.getRevisionName(), 1 - diff --git a/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql b/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql index 47a6f20db3e..3f4790272d2 100644 --- a/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql +++ b/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql @@ -4,6 +4,7 @@ * @id py/function-display-strings * @metricType callable */ + import python from Function f diff --git a/python/ql/src/Metrics/Internal/CallableExtents.ql b/python/ql/src/Metrics/Internal/CallableExtents.ql index 7e2d0baedfa..be617bf2e44 100644 --- a/python/ql/src/Metrics/Internal/CallableExtents.ql +++ b/python/ql/src/Metrics/Internal/CallableExtents.ql @@ -4,6 +4,7 @@ * @id py/function-extents * @metricType callable */ + import python import Extents diff --git a/python/ql/src/Metrics/Internal/CallableSourceLinks.ql b/python/ql/src/Metrics/Internal/CallableSourceLinks.ql index 41278a18684..0e37d683222 100644 --- a/python/ql/src/Metrics/Internal/CallableSourceLinks.ql +++ b/python/ql/src/Metrics/Internal/CallableSourceLinks.ql @@ -4,6 +4,7 @@ * @id py/function-source-links * @metricType callable */ + import python from Function f diff --git a/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql b/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql index 612abfebec7..cf240b42af1 100644 --- a/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql +++ b/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql @@ -4,6 +4,7 @@ * @id py/lgtm/class-display-strings * @metricType reftype */ + import python from Class c diff --git a/python/ql/src/Metrics/Internal/ClassExtents.ql b/python/ql/src/Metrics/Internal/ClassExtents.ql index cc5fd7e9390..b3b3985a8a8 100644 --- a/python/ql/src/Metrics/Internal/ClassExtents.ql +++ b/python/ql/src/Metrics/Internal/ClassExtents.ql @@ -4,6 +4,7 @@ * @id py/class-extents * @metricType reftype */ + import python import Extents diff --git a/python/ql/src/Metrics/Internal/ClassSourceLinks.ql b/python/ql/src/Metrics/Internal/ClassSourceLinks.ql index 089596a0d40..198328f2e8d 100644 --- a/python/ql/src/Metrics/Internal/ClassSourceLinks.ql +++ b/python/ql/src/Metrics/Internal/ClassSourceLinks.ql @@ -4,6 +4,7 @@ * @id py/class-source-links * @metricType reftype */ + import python from Class c diff --git a/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql b/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql index c950cd4bac4..c0ef582c32b 100644 --- a/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql +++ b/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql @@ -3,14 +3,12 @@ * @description Lack of cohesion in the methods of a class, as defined by Chidamber and Kemerer. * @kind treemap * @id py/lack-of-cohesion-chidamber-kemerer - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType reftype * @metricAggregate avg max */ import python - from ClassMetrics cls -select cls, cls.getLackOfCohesionCK() as n -order by n desc +select cls, cls.getLackOfCohesionCK() as n order by n desc diff --git a/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql b/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql index 0a315c44ea7..5cc77ecfb4f 100644 --- a/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql +++ b/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql @@ -3,14 +3,12 @@ * @description Lack of cohesion of a class, as defined by Hitz and Montazeri. * @kind treemap * @id py/lack-of-cohesion-hitz-montazeri - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType reftype * @metricAggregate avg max */ import python - from ClassMetrics cls -select cls, cls.getLackOfCohesionHM() as n -order by n desc +select cls, cls.getLackOfCohesionHM() as n order by n desc diff --git a/python/ql/src/Metrics/ModuleAfferentCoupling.ql b/python/ql/src/Metrics/ModuleAfferentCoupling.ql index f8f5e0c4208..7bf51433785 100644 --- a/python/ql/src/Metrics/ModuleAfferentCoupling.ql +++ b/python/ql/src/Metrics/ModuleAfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ModuleMetrics m -select m, m.getAfferentCoupling() as n -order by n desc - +select m, m.getAfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/ModuleEfferentCoupling.ql b/python/ql/src/Metrics/ModuleEfferentCoupling.ql index be32b8bc561..51fdcf5423b 100644 --- a/python/ql/src/Metrics/ModuleEfferentCoupling.ql +++ b/python/ql/src/Metrics/ModuleEfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ModuleMetrics m -select m, m.getEfferentCoupling() as n -order by n desc - +select m, m.getEfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql b/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql index 4ddd2ba1f0e..00a4c1bf0db 100644 --- a/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql +++ b/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql @@ -12,7 +12,5 @@ import python - from FunctionMetrics func -select func, func.getNumberOfParametersWithoutDefault() as n -order by n desc +select func, func.getNumberOfParametersWithoutDefault() as n order by n desc diff --git a/python/ql/src/Metrics/NumberOfStatements.ql b/python/ql/src/Metrics/NumberOfStatements.ql index 66263f68a84..a5025d8b95d 100644 --- a/python/ql/src/Metrics/NumberOfStatements.ql +++ b/python/ql/src/Metrics/NumberOfStatements.ql @@ -7,9 +7,9 @@ * @metricType file * @metricAggregate avg sum max */ + import python from Module m, int n where n = count(Stmt s | s.getEnclosingModule() = m) -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/TransitiveImports.ql b/python/ql/src/Metrics/TransitiveImports.ql index cea731388f9..a46a7a16302 100644 --- a/python/ql/src/Metrics/TransitiveImports.ql +++ b/python/ql/src/Metrics/TransitiveImports.ql @@ -9,6 +9,7 @@ * @metricAggregate avg max * @tags modularity */ + import python from ModuleValue m, int n diff --git a/python/ql/src/Numerics/Pythagorean.ql b/python/ql/src/Numerics/Pythagorean.ql index 920ec3f326b..6522da8a2b2 100644 --- a/python/ql/src/Numerics/Pythagorean.ql +++ b/python/ql/src/Numerics/Pythagorean.ql @@ -12,37 +12,34 @@ import python predicate squareOp(BinaryExpr e) { - e.getOp() instanceof Pow and e.getRight().(IntegerLiteral).getN() = "2" + e.getOp() instanceof Pow and e.getRight().(IntegerLiteral).getN() = "2" } predicate squareMul(BinaryExpr e) { - e.getOp() instanceof Mult and e.getRight().(Name).getId() = e.getLeft().(Name).getId() + e.getOp() instanceof Mult and e.getRight().(Name).getId() = e.getLeft().(Name).getId() } predicate squareRef(Name e) { - e.isUse() and - exists(SsaVariable v, Expr s | - v.getVariable() = e.getVariable() | - s = v.getDefinition().getNode().getParentNode().(AssignStmt).getValue() and - square(s) - ) + e.isUse() and + exists(SsaVariable v, Expr s | v.getVariable() = e.getVariable() | + s = v.getDefinition().getNode().getParentNode().(AssignStmt).getValue() and + square(s) + ) } predicate square(Expr e) { - squareOp(e) - or - squareMul(e) - or - squareRef(e) + squareOp(e) + or + squareMul(e) + or + squareRef(e) } -from - Call c, - BinaryExpr s +from Call c, BinaryExpr s where - c.getFunc().toString() = "sqrt" and - c.getArg(0) = s and - s.getOp() instanceof Add and - square(s.getLeft()) and square(s.getRight()) -select - c, "Pythagorean calculation with sub-optimal numerics" \ No newline at end of file + c.getFunc().toString() = "sqrt" and + c.getArg(0) = s and + s.getOp() instanceof Add and + square(s.getLeft()) and + square(s.getRight()) +select c, "Pythagorean calculation with sub-optimal numerics" diff --git a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql index 59c7d804b5d..3fb7046f8cc 100644 --- a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql +++ b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql @@ -21,7 +21,8 @@ private string commonTopLevelDomainRegex() { result = "com|org|edu|gov|uk|net|io */ bindingset[pattern] predicate isIncompleteHostNameRegExpPattern(string pattern, string hostPart) { - hostPart = pattern + hostPart = + pattern .regexpCapture("(?i).*" + // an unescaped single `.` "(? 1 and problem = "multiple toStrings()" and what = o.toString() ) @@ -122,55 +163,64 @@ predicate source_object_sanity(string clsname, string problem, string what) { predicate ssa_sanity(string clsname, string problem, string what) { /* Zero or one definitions of each SSA variable */ - exists(SsaVariable var | - clsname = var.getAQlClass() | - uniqueness_error(strictcount(var.getDefinition()), "getDefinition", problem) and what = var.getId() + exists(SsaVariable var | clsname = var.getAQlClass() | + uniqueness_error(strictcount(var.getDefinition()), "getDefinition", problem) and + what = var.getId() ) or /* Dominance criterion: Definition *must* dominate *all* uses. */ exists(SsaVariable var, ControlFlowNode defn, ControlFlowNode use | - defn = var.getDefinition() and use = var.getAUse() | - not defn.strictlyDominates(use) and not defn = use and + defn = var.getDefinition() and use = var.getAUse() + | + not defn.strictlyDominates(use) and + not defn = use and /* Phi nodes which share a flow node with a use come *before* the use */ not (exists(var.getAPhiInput()) and defn = use) and - clsname = var.getAQlClass() and problem = "a definition which does not dominate a use at " + use.getLocation() and what = var.getId() + " at " + var.getLocation() + clsname = var.getAQlClass() and + problem = "a definition which does not dominate a use at " + use.getLocation() and + what = var.getId() + " at " + var.getLocation() ) or /* Minimality of phi nodes */ exists(SsaVariable var | strictcount(var.getAPhiInput()) = 1 and - var.getAPhiInput().getDefinition().getBasicBlock().strictlyDominates(var.getDefinition().getBasicBlock()) - | - clsname = var.getAQlClass() and problem = " a definition which is dominated by the definition of an incoming phi edge." and what = var.getId() + " at " + var.getLocation() + var + .getAPhiInput() + .getDefinition() + .getBasicBlock() + .strictlyDominates(var.getDefinition().getBasicBlock()) + | + clsname = var.getAQlClass() and + problem = " a definition which is dominated by the definition of an incoming phi edge." and + what = var.getId() + " at " + var.getLocation() ) } predicate function_object_sanity(string clsname, string problem, string what) { - exists(FunctionObject func | - clsname = func.getAQlClass() | + exists(FunctionObject func | clsname = func.getAQlClass() | what = func.getName() and ( count(func.descriptiveString()) = 0 and problem = "no descriptiveString()" or - exists(int c | - c = strictcount(func.descriptiveString()) and c > 1 | + exists(int c | c = strictcount(func.descriptiveString()) and c > 1 | problem = c + "descriptiveString()s" ) ) - or + or not exists(func.getName()) and what = "?" and problem = "no name" ) - } predicate multiple_origins_per_object(Object obj) { - not obj.isC() and not obj instanceof ModuleObject and - exists(ControlFlowNode use, Context ctx | strictcount(ControlFlowNode orig | use.refersTo(ctx, obj, _, orig)) > 1) + not obj.isC() and + not obj instanceof ModuleObject and + exists(ControlFlowNode use, Context ctx | + strictcount(ControlFlowNode orig | use.refersTo(ctx, obj, _, orig)) > 1 + ) } predicate intermediate_origins(ControlFlowNode use, ControlFlowNode inter, Object obj) { - exists(ControlFlowNode orig, Context ctx | - not inter = orig | + exists(ControlFlowNode orig, Context ctx | not inter = orig | use.refersTo(ctx, obj, _, inter) and inter.refersTo(ctx, obj, _, orig) and // It can sometimes happen that two different modules (e.g. cPickle and Pickle) @@ -181,8 +231,10 @@ predicate intermediate_origins(ControlFlowNode use, ControlFlowNode inter, Objec predicate points_to_sanity(string clsname, string problem, string what) { exists(Object obj | - multiple_origins_per_object(obj) and clsname = obj.getAQlClass() and - problem = "multiple origins for an object" and what = obj.toString() + multiple_origins_per_object(obj) and + clsname = obj.getAQlClass() and + problem = "multiple origins for an object" and + what = obj.toString() ) or exists(ControlFlowNode use, ControlFlowNode inter, Object obj | @@ -194,8 +246,8 @@ predicate points_to_sanity(string clsname, string problem, string what) { } predicate jump_to_definition_sanity(string clsname, string problem, string what) { - problem = "multiple (jump-to) definitions" and - exists(Expr use | + problem = "multiple (jump-to) definitions" and + exists(Expr use | strictcount(getUniqueDefinition(use)) > 1 and clsname = use.getAQlClass() and what = use.toString() @@ -208,10 +260,12 @@ predicate file_sanity(string clsname, string problem, string what) { problem = "has same name as a folder" and what = file.getAbsolutePath() and what = folder.getAbsolutePath() - ) or + ) + or exists(Container f | clsname = f.getAQlClass() and - uniqueness_error(count(f.toString()), "toString", problem) and what = "file " + f.getName() + uniqueness_error(count(f.toString()), "toString", problem) and + what = "file " + f.getName() ) } @@ -228,17 +282,17 @@ predicate class_value_sanity(string clsname, string problem, string what) { } from string clsname, string problem, string what -where -ast_sanity(clsname, problem, what) or -location_sanity(clsname, problem, what)or -scope_sanity(clsname, problem, what) or -cfg_sanity(clsname, problem, what) or -ssa_sanity(clsname, problem, what) or -builtin_object_sanity(clsname, problem, what) or -source_object_sanity(clsname, problem, what) or -function_object_sanity(clsname, problem, what) or -points_to_sanity(clsname, problem, what) or -jump_to_definition_sanity(clsname, problem, what) or -file_sanity(clsname, problem, what) or -class_value_sanity(clsname, problem, what) +where + ast_sanity(clsname, problem, what) or + location_sanity(clsname, problem, what) or + scope_sanity(clsname, problem, what) or + cfg_sanity(clsname, problem, what) or + ssa_sanity(clsname, problem, what) or + builtin_object_sanity(clsname, problem, what) or + source_object_sanity(clsname, problem, what) or + function_object_sanity(clsname, problem, what) or + points_to_sanity(clsname, problem, what) or + jump_to_definition_sanity(clsname, problem, what) or + file_sanity(clsname, problem, what) or + class_value_sanity(clsname, problem, what) select clsname + " " + what + " has " + problem diff --git a/python/ql/src/analysis/Summary.ql b/python/ql/src/analysis/Summary.ql index ba2fee0b4a8..55564edb16e 100644 --- a/python/ql/src/analysis/Summary.ql +++ b/python/ql/src/analysis/Summary.ql @@ -1,38 +1,43 @@ -/** Summarize a snapshot +/** + * Summarize a snapshot */ import python from string key, string value where -key = "Extractor version" and py_flags_versioned("extractor.version", value, _) -or -key = "Snapshot build time" and exists(date d | snapshotDate(d) and value = d.toString()) -or -key = "Interpreter version" and -exists(string major, string minor | - py_flags_versioned("version.major", major, _) and - py_flags_versioned("version.minor", minor, _) and - value = major + "." + minor -) -or -key = "Build platform" and -exists(string raw | - py_flags_versioned("sys.platform", raw, _) | - if raw = "win32" then - value = "Windows" - else if raw = "linux2" then - value = "Linux" - else if raw = "darwin" then - value = "OSX" - else - value = raw -) -or -key = "Source location" and sourceLocationPrefix(value) -or -key = "Lines of code (source)" and value = sum(ModuleMetrics m | exists(m.getFile().getRelativePath()) | m.getNumberOfLinesOfCode()).toString() -or -key = "Lines of code (total)" and value = sum(ModuleMetrics m | any() | m.getNumberOfLinesOfCode()).toString() - + key = "Extractor version" and py_flags_versioned("extractor.version", value, _) + or + key = "Snapshot build time" and + exists(date d | snapshotDate(d) and value = d.toString()) + or + key = "Interpreter version" and + exists(string major, string minor | + py_flags_versioned("version.major", major, _) and + py_flags_versioned("version.minor", minor, _) and + value = major + "." + minor + ) + or + key = "Build platform" and + exists(string raw | py_flags_versioned("sys.platform", raw, _) | + if raw = "win32" + then value = "Windows" + else + if raw = "linux2" + then value = "Linux" + else + if raw = "darwin" + then value = "OSX" + else value = raw + ) + or + key = "Source location" and sourceLocationPrefix(value) + or + key = "Lines of code (source)" and + value = + sum(ModuleMetrics m | exists(m.getFile().getRelativePath()) | m.getNumberOfLinesOfCode()) + .toString() + or + key = "Lines of code (total)" and + value = sum(ModuleMetrics m | any() | m.getNumberOfLinesOfCode()).toString() select key, value diff --git a/python/ql/src/analysis/TypeHierarchyFailure.ql b/python/ql/src/analysis/TypeHierarchyFailure.ql index 8aac3ea236b..c4c91005743 100644 --- a/python/ql/src/analysis/TypeHierarchyFailure.ql +++ b/python/ql/src/analysis/TypeHierarchyFailure.ql @@ -9,8 +9,6 @@ import python - from Class cls, string reason -where -exists(ClassObject c | c.getPyClass() = cls | c.failedInference(reason)) +where exists(ClassObject c | c.getPyClass() = cls | c.failedInference(reason)) select cls, "Inference of class hierarchy failed for class '" + cls.getName() + "': " + reason + "." diff --git a/python/ql/src/analysis/TypeInferenceFailure.ql b/python/ql/src/analysis/TypeInferenceFailure.ql index 1b8237d65a1..0e6e42e8385 100644 --- a/python/ql/src/analysis/TypeInferenceFailure.ql +++ b/python/ql/src/analysis/TypeInferenceFailure.ql @@ -6,10 +6,11 @@ * @id py/type-inference-failure * @deprecated */ + import python - from ControlFlowNode f, Object o -where f.refersTo(o) and -not exists(ClassObject c | f.refersTo(o, c, _)) -select o, "Type inference fails for 'object'." \ No newline at end of file +where + f.refersTo(o) and + not exists(ClassObject c | f.refersTo(o, c, _)) +select o, "Type inference fails for 'object'." diff --git a/python/ql/src/external/DuplicateBlock.ql b/python/ql/src/external/DuplicateBlock.ql index f9a75f437a2..38aed20739f 100644 --- a/python/ql/src/external/DuplicateBlock.ql +++ b/python/ql/src/external/DuplicateBlock.ql @@ -14,21 +14,21 @@ * @precision medium * @id py/duplicate-block */ + import python import CodeDuplication predicate sorted_by_location(DuplicateBlock x, DuplicateBlock y) { - if x.sourceFile() = y.sourceFile() then - x.sourceStartLine() < y.sourceStartLine() - else - x.sourceFile().getAbsolutePath() < y.sourceFile().getAbsolutePath() + if x.sourceFile() = y.sourceFile() + then x.sourceStartLine() < y.sourceStartLine() + else x.sourceFile().getAbsolutePath() < y.sourceFile().getAbsolutePath() } from DuplicateBlock d, DuplicateBlock other -where d.sourceLines() > 10 and - other.getEquivalenceClass() = d.getEquivalenceClass() and - sorted_by_location(other, d) -select - d, - "Duplicate code: " + d.sourceLines() + " lines are duplicated at " + - other.sourceFile().getShortName() + ":" + other.sourceStartLine().toString() +where + d.sourceLines() > 10 and + other.getEquivalenceClass() = d.getEquivalenceClass() and + sorted_by_location(other, d) +select d, + "Duplicate code: " + d.sourceLines() + " lines are duplicated at " + + other.sourceFile().getShortName() + ":" + other.sourceStartLine().toString() diff --git a/python/ql/src/external/DuplicateFunction.ql b/python/ql/src/external/DuplicateFunction.ql index ddf587caf68..b638f6fb5b2 100644 --- a/python/ql/src/external/DuplicateFunction.ql +++ b/python/ql/src/external/DuplicateFunction.ql @@ -13,19 +13,17 @@ * @precision high * @id py/duplicate-function */ + import python import CodeDuplication -predicate relevant(Function m) { - m.getMetrics().getNumberOfLinesOfCode() > 5 -} +predicate relevant(Function m) { m.getMetrics().getNumberOfLinesOfCode() > 5 } from Function m, Function other, string message, int percent -where duplicateScopes(m, other, percent, message) - and relevant(m) - and percent > 95.0 - and not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) - and not duplicateScopes(m.getScope(), other.getScope(), _, _) -select m, message, - other, - other.getName() +where + duplicateScopes(m, other, percent, message) and + relevant(m) and + percent > 95.0 and + not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and + not duplicateScopes(m.getScope(), other.getScope(), _, _) +select m, message, other, other.getName() diff --git a/python/ql/src/external/MostlyDuplicateClass.ql b/python/ql/src/external/MostlyDuplicateClass.ql index 7a6f0b7587d..88169ab897f 100644 --- a/python/ql/src/external/MostlyDuplicateClass.ql +++ b/python/ql/src/external/MostlyDuplicateClass.ql @@ -13,12 +13,13 @@ * @precision high * @id py/mostly-duplicate-class */ + import python import CodeDuplication from Class c, Class other, string message -where duplicateScopes(c, other, _, message) - and count(c.getAStmt()) > 3 - and not duplicateScopes(c.getEnclosingModule(), _, _, _) +where + duplicateScopes(c, other, _, message) and + count(c.getAStmt()) > 3 and + not duplicateScopes(c.getEnclosingModule(), _, _, _) select c, message, other, other.getName() - diff --git a/python/ql/src/external/MostlyDuplicateFile.ql b/python/ql/src/external/MostlyDuplicateFile.ql index 57178d8846e..78df1a4166e 100644 --- a/python/ql/src/external/MostlyDuplicateFile.ql +++ b/python/ql/src/external/MostlyDuplicateFile.ql @@ -13,6 +13,7 @@ * @precision high * @id py/mostly-duplicate-file */ + import python import CodeDuplication diff --git a/python/ql/src/external/MostlySimilarFile.ql b/python/ql/src/external/MostlySimilarFile.ql index 4bdcce626c9..97413885962 100644 --- a/python/ql/src/external/MostlySimilarFile.ql +++ b/python/ql/src/external/MostlySimilarFile.ql @@ -9,11 +9,11 @@ * duplicate-code * statistical * non-attributable - * @problem.severity recommendation * @sub-severity low * @precision high * @id py/mostly-similar-file */ + import python import CodeDuplication diff --git a/python/ql/src/external/SimilarFunction.ql b/python/ql/src/external/SimilarFunction.ql index 9d0a3f72cfb..bcd63a41dcf 100644 --- a/python/ql/src/external/SimilarFunction.ql +++ b/python/ql/src/external/SimilarFunction.ql @@ -13,23 +13,18 @@ * @precision very-high * @id py/similar-function */ + import python import CodeDuplication -predicate relevant(Function m) { - m.getMetrics().getNumberOfLinesOfCode() > 10 -} +predicate relevant(Function m) { m.getMetrics().getNumberOfLinesOfCode() > 10 } from Function m, Function other, string message, int percent -where similarScopes(m, other, percent, message) and +where + similarScopes(m, other, percent, message) and relevant(m) and percent > 95.0 and not duplicateScopes(m, other, _, _) and not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and not duplicateScopes(m.getScope(), other.getScope(), _, _) -select m, message, - other, - other.getName() - - - +select m, message, other, other.getName() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql index f5279480573..620944de5b9 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,6 +1,5 @@ - import python from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) -select ex.getLocation().getStartLine(), ex.toString(), val.toString() \ No newline at end of file +select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql index 6fe92327f62..56498054f51 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql @@ -1,5 +1,4 @@ - import python from RaisingNode r -select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql index d23a5efe2f4..80831a9ca54 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql @@ -1,7 +1,7 @@ - import python from ControlFlowNode r, ControlFlowNode s -where s = r.getAnExceptionalSuccessor() and -not r.(RaisingNode).unlikelySuccessor(s) -select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +where + s = r.getAnExceptionalSuccessor() and + not r.(RaisingNode).unlikelySuccessor(s) +select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql index d8db11d9f1b..29bad86bf0f 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql @@ -1,6 +1,5 @@ - import python from RaisingNode r where r.raisesUnknownType() -select r.getLocation().getStartLine(), r.toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString() diff --git a/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql b/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql index a10b6bef24a..94a1db9b83d 100644 --- a/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql +++ b/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql @@ -1,11 +1,12 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext from ControlFlowNode f, Location l, Context c - -where not PointsToInternal::reachableBlock(f.getBasicBlock(), c) and c.isImport() and -(f.getNode() instanceof FunctionExpr or f.getNode() instanceof ClassExpr) and -l = f.getLocation() and l.getFile().getShortName() = "test.py" +where + not PointsToInternal::reachableBlock(f.getBasicBlock(), c) and + c.isImport() and + (f.getNode() instanceof FunctionExpr or f.getNode() instanceof ClassExpr) and + l = f.getLocation() and + l.getFile().getShortName() = "test.py" select l.getStartLine() diff --git a/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql b/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql index 25097057d07..44a35b27b27 100644 --- a/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql +++ b/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql @@ -1,9 +1,10 @@ - import python from int line, ControlFlowNode f, Object o, ControlFlowNode orig -where - not f.getLocation().getFile().inStdlib() and - f.refersTo(o, orig) and line = f.getLocation().getStartLine() and line != 0 and - not o instanceof NumericObject // Omit sys.hexversion as it will change between machines +where + not f.getLocation().getFile().inStdlib() and + f.refersTo(o, orig) and + line = f.getLocation().getStartLine() and + line != 0 and + not o instanceof NumericObject // Omit sys.hexversion as it will change between machines select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), orig.toString() diff --git a/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql index b658eb84474..68eec976105 100644 --- a/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql @@ -1,4 +1,3 @@ - import python from ClassObject cls diff --git a/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql b/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql index 70ef57c16c2..6cd800ac399 100644 --- a/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql +++ b/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql @@ -1,14 +1,11 @@ import python -string short_loc(Location l) { - result = l.getFile().getShortName() + ":" + l.getStartLine() -} +string short_loc(Location l) { result = l.getFile().getShortName() + ":" + l.getStartLine() } from ControlFlowNode use, Object obj, ControlFlowNode orig, int line - -where use.refersTo(obj, orig) and -use.getLocation().getFile().getShortName() = "test.py" and -line = use.getLocation().getStartLine() and -not line = 0 - +where + use.refersTo(obj, orig) and + use.getLocation().getFile().getShortName() = "test.py" and + line = use.getLocation().getStartLine() and + not line = 0 select line, use.toString(), obj.toString(), short_loc(orig.getLocation()) diff --git a/python/ql/test/2/library-tests/classes/attr/class_attr.ql b/python/ql/test/2/library-tests/classes/attr/class_attr.ql index 0b283debd5d..3b7bf8b3ba0 100644 --- a/python/ql/test/2/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/class_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") -select line, cls.toString(), name, obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") +select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql index a274a1dd95b..2f16aa4ca97 100644 --- a/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.hasAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.hasAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/2/library-tests/classes/attr/list_attr.ql b/python/ql/test/2/library-tests/classes/attr/list_attr.ql index 2977030252a..aad2d9489c3 100644 --- a/python/ql/test/2/library-tests/classes/attr/list_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/list_attr.ql @@ -7,10 +7,10 @@ import python from ClassObject cls, string name, Object what -where -(cls.getName() = "list" or - cls.getASuperType().getName() = "list" -) -and -cls.lookupAttribute(name) = what +where + ( + cls.getName() = "list" or + cls.getASuperType().getName() = "list" + ) and + cls.lookupAttribute(name) = what select cls.toString(), name, what.toString() diff --git a/python/ql/test/2/library-tests/classes/mro/C3.ql b/python/ql/test/2/library-tests/classes/mro/C3.ql index d04f49af51c..c4b0dd896d6 100644 --- a/python/ql/test/2/library-tests/classes/mro/C3.ql +++ b/python/ql/test/2/library-tests/classes/mro/C3.ql @@ -1,18 +1,12 @@ - import python import semmle.python.pointsto.MRO import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal ClassList mro(ClassObjectInternal cls) { - if Types::isNewStyle(cls) then - result = Mro::newStyleMro(cls) - else - result = Mro::oldStyleMro(cls) + if Types::isNewStyle(cls) then result = Mro::newStyleMro(cls) else result = Mro::oldStyleMro(cls) } from ClassObjectInternal cls where not cls.isBuiltin() - select cls.toString(), mro(cls) - diff --git a/python/ql/test/2/library-tests/classes/mro/mro.ql b/python/ql/test/2/library-tests/classes/mro/mro.ql index 0695e6ce5b8..122d31c4a9b 100644 --- a/python/ql/test/2/library-tests/classes/mro/mro.ql +++ b/python/ql/test/2/library-tests/classes/mro/mro.ql @@ -1,8 +1,7 @@ - - import python from ClassObject cls, ClassObject l, ClassObject r -where not cls.isC() and -r = cls.nextInMro(l) +where + not cls.isC() and + r = cls.nextInMro(l) select cls.toString(), l.toString(), r.toString() diff --git a/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql b/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql index 29dc596401c..475505620f4 100644 --- a/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql +++ b/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql @@ -4,4 +4,6 @@ import python - select count(Comprehension c | count(c.toString()) != 1 or count(c.getLocation()) != 1 or not exists(c.getAFlowNode())) +select count(Comprehension c | + count(c.toString()) != 1 or count(c.getLocation()) != 1 or not exists(c.getAFlowNode()) + ) diff --git a/python/ql/test/2/library-tests/locations/general/AllLocations.ql b/python/ql/test/2/library-tests/locations/general/AllLocations.ql index 981d4560d87..9e6fcb00a05 100644 --- a/python/ql/test/2/library-tests/locations/general/AllLocations.ql +++ b/python/ql/test/2/library-tests/locations/general/AllLocations.ql @@ -9,8 +9,7 @@ import python from string classname where -exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) -or -exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) - + exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) + or + exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) select classname diff --git a/python/ql/test/2/library-tests/locations/general/Locations.ql b/python/ql/test/2/library-tests/locations/general/Locations.ql index 874eecbdb9f..b2e7f4b164d 100644 --- a/python/ql/test/2/library-tests/locations/general/Locations.ql +++ b/python/ql/test/2/library-tests/locations/general/Locations.ql @@ -1,6 +1,5 @@ import python - from AstNode ast, Location l where ast.getLocation() = l -select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/2/library-tests/locations/general/Prefix.ql b/python/ql/test/2/library-tests/locations/general/Prefix.ql index ad608f84cc2..bee9e555cc6 100644 --- a/python/ql/test/2/library-tests/locations/general/Prefix.ql +++ b/python/ql/test/2/library-tests/locations/general/Prefix.ql @@ -1,5 +1,4 @@ import python - -from StrConst s -select s.getLocation().getStartLine(), s.getText(), s.getPrefix() \ No newline at end of file +from StrConst s +select s.getLocation().getStartLine(), s.getText(), s.getPrefix() diff --git a/python/ql/test/2/library-tests/locations/keywords/Locations.ql b/python/ql/test/2/library-tests/locations/keywords/Locations.ql index b638ea81e14..afe685d0864 100644 --- a/python/ql/test/2/library-tests/locations/keywords/Locations.ql +++ b/python/ql/test/2/library-tests/locations/keywords/Locations.ql @@ -1,6 +1,5 @@ import python - from Keyword k, Location l where k.getLocation() = l -select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/2/library-tests/locations/strings/test.ql b/python/ql/test/2/library-tests/locations/strings/test.ql index 4a23a61d0da..be3052d9500 100644 --- a/python/ql/test/2/library-tests/locations/strings/test.ql +++ b/python/ql/test/2/library-tests/locations/strings/test.ql @@ -2,4 +2,4 @@ import python from StrConst s, int bl, int bc, int el, int ec where s.getLocation().hasLocationInfo(_, bl, bc, el, ec) -select bl, bc, el, ec, s.getText() \ No newline at end of file +select bl, bc, el, ec, s.getText() diff --git a/python/ql/test/2/library-tests/modules/general/import_test.ql b/python/ql/test/2/library-tests/modules/general/import_test.ql index 026dcf2c690..94f8c1447ca 100644 --- a/python/ql/test/2/library-tests/modules/general/import_test.ql +++ b/python/ql/test/2/library-tests/modules/general/import_test.ql @@ -1,7 +1,9 @@ import python from ImportExpr ie, string m, string t, string r -where m = ie.getImportedModuleName() and -(if ie.isTop() then t = "top" else t = "bottom") and -(if ie.isRelative() then r= "relative" else r = "absolute") -select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, r, m +where + m = ie.getImportedModuleName() and + (if ie.isTop() then t = "top" else t = "bottom") and + (if ie.isRelative() then r = "relative" else r = "absolute") +select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, + r, m diff --git a/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql b/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql index e3fde98513f..50f79a57aed 100644 --- a/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql +++ b/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql @@ -1,4 +1,3 @@ - import python from ModuleObject m, string name diff --git a/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql b/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql index 9109fcb98a8..50ded7b4124 100644 --- a/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql +++ b/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql @@ -2,4 +2,4 @@ import python from ModuleObject m, string name where not m.isC() and m.importedAs(name) -select m.toString(), name \ No newline at end of file +select m.toString(), name diff --git a/python/ql/test/2/library-tests/objects/Literals.ql b/python/ql/test/2/library-tests/objects/Literals.ql index f83f4e722da..ad6e1181cfd 100644 --- a/python/ql/test/2/library-tests/objects/Literals.ql +++ b/python/ql/test/2/library-tests/objects/Literals.ql @@ -1,8 +1,6 @@ - /* Test that there are no literals that do not have a corresponding object. */ import python - string repr(Expr e) { result = e.(Num).getN() or result = e.(Bytes).getS() or @@ -10,7 +8,5 @@ string repr(Expr e) { } from ImmutableLiteral l -where -not exists(l.getLiteralObject()) - -select l.getLocation().getStartLine(), repr(l) \ No newline at end of file +where not exists(l.getLiteralObject()) +select l.getLocation().getStartLine(), repr(l) diff --git a/python/ql/test/2/library-tests/types/classes/mro_test.ql b/python/ql/test/2/library-tests/types/classes/mro_test.ql index 181c8205289..fa2ac44d4d2 100644 --- a/python/ql/test/2/library-tests/types/classes/mro_test.ql +++ b/python/ql/test/2/library-tests/types/classes/mro_test.ql @@ -1,7 +1,5 @@ - import python from ClassObject cls where not cls.isC() select cls.toString(), cls.getMro() - diff --git a/python/ql/test/2/library-tests/types/classes/new_style.ql b/python/ql/test/2/library-tests/types/classes/new_style.ql index 5c66eff3e60..a0cd38b9e62 100644 --- a/python/ql/test/2/library-tests/types/classes/new_style.ql +++ b/python/ql/test/2/library-tests/types/classes/new_style.ql @@ -1,13 +1,8 @@ - import python from ClassObject cls, string style -where not cls.isC() and -not cls.failedInference() and -( - if cls.isNewStyle() then - style = "new" - else - style = "old" -) +where + not cls.isC() and + not cls.failedInference() and + (if cls.isNewStyle() then style = "new" else style = "old") select cls.toString(), style diff --git a/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql b/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql index 33c6b003b99..8e4c47a3e74 100644 --- a/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql +++ b/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql @@ -2,5 +2,4 @@ import python from RaisingNode r, Scope s, ClassObject cls where r.viableExceptionalExit(s, cls) - select r.getLocation().getStartLine(), r.toString(), s.toString(), cls.toString() diff --git a/python/ql/test/2/library-tests/types/exceptions/Raises.ql b/python/ql/test/2/library-tests/types/exceptions/Raises.ql index b003fd03dfa..aa477f718a2 100644 --- a/python/ql/test/2/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/2/library-tests/types/exceptions/Raises.ql @@ -1,13 +1,12 @@ - import python from PyFunctionObject f, string type -where +where type = f.getARaisedType().toString() or type = "Unknown" and f.raisesUnknownType() or not exists(f.getARaisedType()) and - not f.raisesUnknownType() and type = "None" - -select f.toString(), type \ No newline at end of file + not f.raisesUnknownType() and + type = "None" +select f.toString(), type diff --git a/python/ql/test/2/library-tests/types/functions/Calls.ql b/python/ql/test/2/library-tests/types/functions/Calls.ql index 87ee8a1f9d2..6fc188753e5 100644 --- a/python/ql/test/2/library-tests/types/functions/Calls.ql +++ b/python/ql/test/2/library-tests/types/functions/Calls.ql @@ -1,4 +1,3 @@ - import python from FunctionObject func, ControlFlowNode call diff --git a/python/ql/test/2/library-tests/types/functions/Never.ql b/python/ql/test/2/library-tests/types/functions/Never.ql index 3dcf47ffd4d..1e43ead7dce 100644 --- a/python/ql/test/2/library-tests/types/functions/Never.ql +++ b/python/ql/test/2/library-tests/types/functions/Never.ql @@ -2,4 +2,4 @@ import python from FunctionObject func where func.neverReturns() -select func.getOrigin().getLocation().getStartLine(), func.getName() \ No newline at end of file +select func.getOrigin().getLocation().getStartLine(), func.getName() diff --git a/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql b/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql index a200a947ab0..beb955e1188 100644 --- a/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql +++ b/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql @@ -1,7 +1,5 @@ - import python from PyFunctionObject func, ClassObject ret_type where func.getAnInferredReturnType() = ret_type - select func.getOrigin().getLocation().getStartLine(), func.getName(), ret_type.toString() diff --git a/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql b/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql index 7fd60f2e058..6ff0563e787 100644 --- a/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql +++ b/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql @@ -1,7 +1,8 @@ import python from ClassObject cls, string name, BuiltinPropertyObject p -where cls.declaredAttribute(name) = p and -(cls = theObjectType() or cls = theListType() or cls = theTypeType()) - -select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), p.getDeleter().toString() +where + cls.declaredAttribute(name) = p and + (cls = theObjectType() or cls = theListType() or cls = theTypeType()) +select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), + p.getDeleter().toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql index f5279480573..620944de5b9 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,6 +1,5 @@ - import python from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) -select ex.getLocation().getStartLine(), ex.toString(), val.toString() \ No newline at end of file +select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql index 6fe92327f62..56498054f51 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql @@ -1,5 +1,4 @@ - import python from RaisingNode r -select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql index d23a5efe2f4..80831a9ca54 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql @@ -1,7 +1,7 @@ - import python from ControlFlowNode r, ControlFlowNode s -where s = r.getAnExceptionalSuccessor() and -not r.(RaisingNode).unlikelySuccessor(s) -select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +where + s = r.getAnExceptionalSuccessor() and + not r.(RaisingNode).unlikelySuccessor(s) +select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql index d8db11d9f1b..29bad86bf0f 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql @@ -1,6 +1,5 @@ - import python from RaisingNode r where r.raisesUnknownType() -select r.getLocation().getStartLine(), r.toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString() diff --git a/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql b/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql index 575d347fc10..cc191d7c7d8 100644 --- a/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql +++ b/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql @@ -1,7 +1,5 @@ import python from ControlFlowNode f, Object o, ControlFlowNode x - where f.refersTo(o, x) - select f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql b/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql index 47b1cbc5434..0c6149c38b1 100644 --- a/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql +++ b/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql @@ -1,7 +1,6 @@ import python from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - where f.refersTo(o, c, x) - -select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), x.getLocation().getStartLine() +select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), + x.getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql index a4543881042..6215714a25e 100644 --- a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql +++ b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql @@ -2,13 +2,8 @@ import python import semmle.python.pointsto.PointsTo from ControlFlowNode f, Context c, boolean b - -where -exists(Object obj | - PointsTo::points_to(f, c, obj, _, _) and obj.booleanValue() = b -) and -not exists(Object obj | - PointsTo::points_to(f, c, obj, _, _) and not obj.booleanValue() = b -) - -select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), c.toString(), b +where + exists(Object obj | PointsTo::points_to(f, c, obj, _, _) and obj.booleanValue() = b) and + not exists(Object obj | PointsTo::points_to(f, c, obj, _, _) and not obj.booleanValue() = b) +select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), + c.toString(), b diff --git a/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql b/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql index 844992f663e..d07dc65c34f 100644 --- a/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql +++ b/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql @@ -1,7 +1,9 @@ - import python import semmle.python.pointsto.PointsTo from ControlFlowNode f, Location l -where not PointsToInternal::reachableBlock(f.getBasicBlock(), _) and l = f.getLocation() and l.getFile().getShortName() = "test.py" +where + not PointsToInternal::reachableBlock(f.getBasicBlock(), _) and + l = f.getLocation() and + l.getFile().getShortName() = "test.py" select l.getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql b/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql index d35ac04bb30..f91d207fc70 100644 --- a/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql +++ b/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql @@ -1,8 +1,5 @@ - import python from Call c, FunctionObject f - where f.getACall().getNode() = c - select c.getLocation().getStartLine(), f.toString(), f.getFunction().getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql index b658eb84474..68eec976105 100644 --- a/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql @@ -1,4 +1,3 @@ - import python from ClassObject cls diff --git a/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql b/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql index b6f1ce2da98..e21a864b8bb 100644 --- a/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql +++ b/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql @@ -1,10 +1,11 @@ import python // as used in semmle.python.filters.Tests - from ClassValue c, string base where c.getScope().getLocation().getFile().getShortName().matches("mwe%.py") and c.getName() = "MyTest" and - if exists(c.getABaseType()) then base = c.getABaseType().toString() else base = "" + if exists(c.getABaseType()) + then base = c.getABaseType().toString() + else base = "" select c, base diff --git a/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql b/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql index d8e877aa437..8716d38f086 100644 --- a/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql +++ b/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql @@ -1,8 +1,7 @@ - import python from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin where - f.pointsTo(ctx, v, origin) and - f.getLocation().getFile().getBaseName() = "test.py" + f.pointsTo(ctx, v, origin) and + f.getLocation().getFile().getBaseName() = "test.py" select f.getLocation(), f.toString(), ctx, v diff --git a/python/ql/test/3/library-tests/classes/attr/class_attr.ql b/python/ql/test/3/library-tests/classes/attr/class_attr.ql index 0b283debd5d..3b7bf8b3ba0 100644 --- a/python/ql/test/3/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/3/library-tests/classes/attr/class_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") -select line, cls.toString(), name, obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") +select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql index a274a1dd95b..2f16aa4ca97 100644 --- a/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.hasAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.hasAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/3/library-tests/classes/meta/meta.ql b/python/ql/test/3/library-tests/classes/meta/meta.ql index c295fc330f2..96e26b3f060 100644 --- a/python/ql/test/3/library-tests/classes/meta/meta.ql +++ b/python/ql/test/3/library-tests/classes/meta/meta.ql @@ -1,4 +1,4 @@ import python from ClassExpr cls -select cls.toString(), cls.getMetaClass().toString() \ No newline at end of file +select cls.toString(), cls.getMetaClass().toString() diff --git a/python/ql/test/3/library-tests/classes/meta/meta_obj.ql b/python/ql/test/3/library-tests/classes/meta/meta_obj.ql index f4f91869069..e85127a9305 100644 --- a/python/ql/test/3/library-tests/classes/meta/meta_obj.ql +++ b/python/ql/test/3/library-tests/classes/meta/meta_obj.ql @@ -2,4 +2,4 @@ import python from ClassObject cls where not cls.isC() -select cls.toString(), cls.getAnInferredType().toString() \ No newline at end of file +select cls.toString(), cls.getAnInferredType().toString() diff --git a/python/ql/test/3/library-tests/classes/mro/mro.ql b/python/ql/test/3/library-tests/classes/mro/mro.ql index 87f7e35c7bc..2c710a18eeb 100644 --- a/python/ql/test/3/library-tests/classes/mro/mro.ql +++ b/python/ql/test/3/library-tests/classes/mro/mro.ql @@ -7,6 +7,7 @@ import python from ClassObject cls, ClassObject l, ClassObject r -where not cls.isC() and -r = cls.nextInMro(l) +where + not cls.isC() and + r = cls.nextInMro(l) select cls.toString(), l.toString(), r.toString() diff --git a/python/ql/test/3/library-tests/classes/mro/mro_index.ql b/python/ql/test/3/library-tests/classes/mro/mro_index.ql index f8398bcb737..641667e28f1 100644 --- a/python/ql/test/3/library-tests/classes/mro/mro_index.ql +++ b/python/ql/test/3/library-tests/classes/mro/mro_index.ql @@ -7,6 +7,7 @@ import python from ClassObject cls, ClassObject sup, int index -where sup = cls.getMroItem(index) and -not cls.isC() +where + sup = cls.getMroItem(index) and + not cls.isC() select cls.toString(), index, sup.toString() diff --git a/python/ql/test/3/library-tests/locations/annotations/Locations.ql b/python/ql/test/3/library-tests/locations/annotations/Locations.ql index 66428d5e8ad..211f6ee47df 100644 --- a/python/ql/test/3/library-tests/locations/annotations/Locations.ql +++ b/python/ql/test/3/library-tests/locations/annotations/Locations.ql @@ -1,6 +1,5 @@ import python - from AstNode a, Location l where a.getLocation() = l -select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn(), a.toString() \ No newline at end of file +select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn(), a.toString() diff --git a/python/ql/test/3/library-tests/locations/general/AllLocations.ql b/python/ql/test/3/library-tests/locations/general/AllLocations.ql index 981d4560d87..9e6fcb00a05 100644 --- a/python/ql/test/3/library-tests/locations/general/AllLocations.ql +++ b/python/ql/test/3/library-tests/locations/general/AllLocations.ql @@ -9,8 +9,7 @@ import python from string classname where -exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) -or -exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) - + exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) + or + exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) select classname diff --git a/python/ql/test/3/library-tests/locations/general/Locations.ql b/python/ql/test/3/library-tests/locations/general/Locations.ql index 874eecbdb9f..b2e7f4b164d 100644 --- a/python/ql/test/3/library-tests/locations/general/Locations.ql +++ b/python/ql/test/3/library-tests/locations/general/Locations.ql @@ -1,6 +1,5 @@ import python - from AstNode ast, Location l where ast.getLocation() = l -select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/3/library-tests/locations/general/Prefix.ql b/python/ql/test/3/library-tests/locations/general/Prefix.ql index ad608f84cc2..bee9e555cc6 100644 --- a/python/ql/test/3/library-tests/locations/general/Prefix.ql +++ b/python/ql/test/3/library-tests/locations/general/Prefix.ql @@ -1,5 +1,4 @@ import python - -from StrConst s -select s.getLocation().getStartLine(), s.getText(), s.getPrefix() \ No newline at end of file +from StrConst s +select s.getLocation().getStartLine(), s.getText(), s.getPrefix() diff --git a/python/ql/test/3/library-tests/locations/keywords/Locations.ql b/python/ql/test/3/library-tests/locations/keywords/Locations.ql index b638ea81e14..afe685d0864 100644 --- a/python/ql/test/3/library-tests/locations/keywords/Locations.ql +++ b/python/ql/test/3/library-tests/locations/keywords/Locations.ql @@ -1,6 +1,5 @@ import python - from Keyword k, Location l where k.getLocation() = l -select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/3/library-tests/modules/general/import_test.ql b/python/ql/test/3/library-tests/modules/general/import_test.ql index 026dcf2c690..94f8c1447ca 100644 --- a/python/ql/test/3/library-tests/modules/general/import_test.ql +++ b/python/ql/test/3/library-tests/modules/general/import_test.ql @@ -1,7 +1,9 @@ import python from ImportExpr ie, string m, string t, string r -where m = ie.getImportedModuleName() and -(if ie.isTop() then t = "top" else t = "bottom") and -(if ie.isRelative() then r= "relative" else r = "absolute") -select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, r, m +where + m = ie.getImportedModuleName() and + (if ie.isTop() then t = "top" else t = "bottom") and + (if ie.isRelative() then r = "relative" else r = "absolute") +select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, + r, m diff --git a/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql b/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql index 39c8aaab471..a3a1ac6b185 100644 --- a/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql +++ b/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql @@ -1,4 +1,3 @@ - import python from ModuleObject m, string name diff --git a/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql b/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql +++ b/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/3/library-tests/types/classes/mro_test.ql b/python/ql/test/3/library-tests/types/classes/mro_test.ql index cb067035076..04b65ae2bef 100644 --- a/python/ql/test/3/library-tests/types/classes/mro_test.ql +++ b/python/ql/test/3/library-tests/types/classes/mro_test.ql @@ -1,7 +1,5 @@ - import python from ClassObject cls, ClassObject sup where not cls.isC() select cls.toString(), sup.toString(), cls.nextInMro(sup).toString() - diff --git a/python/ql/test/3/library-tests/types/exceptions/Raises.ql b/python/ql/test/3/library-tests/types/exceptions/Raises.ql index b003fd03dfa..aa477f718a2 100644 --- a/python/ql/test/3/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/3/library-tests/types/exceptions/Raises.ql @@ -1,13 +1,12 @@ - import python from PyFunctionObject f, string type -where +where type = f.getARaisedType().toString() or type = "Unknown" and f.raisesUnknownType() or not exists(f.getARaisedType()) and - not f.raisesUnknownType() and type = "None" - -select f.toString(), type \ No newline at end of file + not f.raisesUnknownType() and + type = "None" +select f.toString(), type diff --git a/python/ql/test/3/library-tests/types/exceptions/Viable.ql b/python/ql/test/3/library-tests/types/exceptions/Viable.ql index 544b0a0d0b6..e28fa1a907c 100644 --- a/python/ql/test/3/library-tests/types/exceptions/Viable.ql +++ b/python/ql/test/3/library-tests/types/exceptions/Viable.ql @@ -1,7 +1,6 @@ - - import python from RaisingNode r, ControlFlowNode n, ClassObject ex where r.viableExceptionEdge(n, ex) -select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), n.getNode().toString(), ex.toString() +select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), + n.getNode().toString(), ex.toString() diff --git a/python/ql/test/3/library-tests/types/functions/Calls.ql b/python/ql/test/3/library-tests/types/functions/Calls.ql index 608ad79bdfb..6fc188753e5 100644 --- a/python/ql/test/3/library-tests/types/functions/Calls.ql +++ b/python/ql/test/3/library-tests/types/functions/Calls.ql @@ -1,7 +1,5 @@ - import python from FunctionObject func, ControlFlowNode call where func.getACall() = call select call.getLocation().getStartLine(), call.toString(), func.toString() - diff --git a/python/ql/test/3/library-tests/types/functions/Never.ql b/python/ql/test/3/library-tests/types/functions/Never.ql index 3dcf47ffd4d..1e43ead7dce 100644 --- a/python/ql/test/3/library-tests/types/functions/Never.ql +++ b/python/ql/test/3/library-tests/types/functions/Never.ql @@ -2,4 +2,4 @@ import python from FunctionObject func where func.neverReturns() -select func.getOrigin().getLocation().getStartLine(), func.getName() \ No newline at end of file +select func.getOrigin().getLocation().getStartLine(), func.getName() diff --git a/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql b/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql index a200a947ab0..beb955e1188 100644 --- a/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql +++ b/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql @@ -1,7 +1,5 @@ - import python from PyFunctionObject func, ClassObject ret_type where func.getAnInferredReturnType() = ret_type - select func.getOrigin().getLocation().getStartLine(), func.getName(), ret_type.toString() diff --git a/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql b/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql index 6997fd80635..4a35fae7e8b 100644 --- a/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql +++ b/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql @@ -8,17 +8,17 @@ import python from Scope s, string name, Object val -where name != "__name__" and -( - exists(ModuleObject m | - m.getModule() = s and - m.attributeRefersTo(name, val, _) - ) - or - exists(ClassObject cls | - cls.getPyClass() = s and - cls.declaredAttribute(name) = val - ) -) - -select s.toString(), name, val.toString() \ No newline at end of file +where + name != "__name__" and + ( + exists(ModuleObject m | + m.getModule() = s and + m.attributeRefersTo(name, val, _) + ) + or + exists(ClassObject cls | + cls.getPyClass() = s and + cls.declaredAttribute(name) = val + ) + ) +select s.toString(), name, val.toString() diff --git a/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql b/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql index 7fd60f2e058..6ff0563e787 100644 --- a/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql +++ b/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql @@ -1,7 +1,8 @@ import python from ClassObject cls, string name, BuiltinPropertyObject p -where cls.declaredAttribute(name) = p and -(cls = theObjectType() or cls = theListType() or cls = theTypeType()) - -select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), p.getDeleter().toString() +where + cls.declaredAttribute(name) = p and + (cls = theObjectType() or cls = theListType() or cls = theTypeType()) +select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), + p.getDeleter().toString() diff --git a/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql b/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql index 41efa249c31..54e7ed36333 100644 --- a/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql +++ b/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql @@ -1,17 +1,15 @@ - import python /*Find any Definition, assigned value pairs that 'valueForDefinition' misses */ - Expr assignedValue(Name n) { exists(Assign a | a.getATarget() = n and result = a.getValue()) or exists(Alias a | a.getAsname() = n and result = a.getValue()) } -from Name def, DefinitionNode d -where d = def.getAFlowNode() and - exists(assignedValue(def)) and - not d.getValue().getNode() = assignedValue(def) - -select def.toString(), assignedValue(def) \ No newline at end of file +from Name def, DefinitionNode d +where + d = def.getAFlowNode() and + exists(assignedValue(def)) and + not d.getValue().getNode() = assignedValue(def) +select def.toString(), assignedValue(def) diff --git a/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql b/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql index d356ea5de43..a4b98183c27 100644 --- a/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql +++ b/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql @@ -1,10 +1,10 @@ import python -int lineof(ControlFlowNode f) { - result = f.getNode().getLocation().getStartLine() -} +int lineof(ControlFlowNode f) { result = f.getNode().getLocation().getStartLine() } from ControlFlowNode defn, ControlFlowNode use -where defn.getNode() = use.getNode() -and defn.isStore() and use.isLoad() +where + defn.getNode() = use.getNode() and + defn.isStore() and + use.isLoad() select defn.toString(), use.toString(), lineof(defn) diff --git a/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql b/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql index 8ac3a4de0c1..c97f8446345 100644 --- a/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql +++ b/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql @@ -1,21 +1,16 @@ - import python string kind(ControlFlowNode f) { - if f.isAugLoad() then - result = "aug load" + if f.isAugLoad() + then result = "aug load" else ( - if f.isAugStore() then - result = "aug store" + if f.isAugStore() + then result = "aug store" else ( - if f.isLoad() then - result = "load" - else ( - f.isStore() and result = "store" - ) + if f.isLoad() then result = "load" else (f.isStore() and result = "store") ) - ) + ) } from ControlFlowNode cfg -select cfg.getLocation().getStartLine(), cfg, kind(cfg) \ No newline at end of file +select cfg.getLocation().getStartLine(), cfg, kind(cfg) diff --git a/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql b/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql index 7706226bcfa..0222099924b 100644 --- a/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql +++ b/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql @@ -7,7 +7,6 @@ import python - from ControlFlowNode defn, SsaVariable v, AugAssign a, BinaryExpr b -where v.getDefinition() = defn and a.getOperation() = b and b.contains((Expr)defn.getNode()) -select defn.toString(), defn.getNode().getLocation().getStartLine() \ No newline at end of file +where v.getDefinition() = defn and a.getOperation() = b and b.contains(defn.getNode().(Expr)) +select defn.toString(), defn.getNode().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql b/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql index 5e66d239419..13e4736e6d9 100644 --- a/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql +++ b/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql @@ -8,10 +8,11 @@ import python from CompareNode c, NameNode l, NameNode r, Cmpop op, int line, Variable vl, Variable vr -where c.operands(l, op, r) and -line = c.getLocation().getStartLine() and -line = l.getLocation().getStartLine() and -line = r.getLocation().getStartLine() and -l.uses(vl) and r.uses(vr) +where + c.operands(l, op, r) and + line = c.getLocation().getStartLine() and + line = l.getLocation().getStartLine() and + line = r.getLocation().getStartLine() and + l.uses(vl) and + r.uses(vr) select line, c.toString(), vl.getId(), vr.getId(), op.getSymbol() - diff --git a/python/ql/test/library-tests/ControlFlow/delete/test.ql b/python/ql/test/library-tests/ControlFlow/delete/test.ql index 517733b70d6..2aaa45ea719 100644 --- a/python/ql/test/library-tests/ControlFlow/delete/test.ql +++ b/python/ql/test/library-tests/ControlFlow/delete/test.ql @@ -2,4 +2,5 @@ import python from ControlFlowNode p, ControlFlowNode s where p.getASuccessor() = s -select p.getLocation().getStartLine().toString(), p.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +select p.getLocation().getStartLine().toString(), p.toString(), s.getLocation().getStartLine(), + s.toString() diff --git a/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql b/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql index cb53879e63b..d39328e44c7 100644 --- a/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql +++ b/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql @@ -1,9 +1,8 @@ - import python -select count(BasicBlock b1, BasicBlock b2 -| b1 = b2.getImmediateDominator+() and not b1.strictlyDominates(b2) -), -count(BasicBlock b1, BasicBlock b2 -| not b1 = b2.getImmediateDominator+() and b1.strictlyDominates(b2) -) +select count(BasicBlock b1, BasicBlock b2 | + b1 = b2.getImmediateDominator+() and not b1.strictlyDominates(b2) + ), + count(BasicBlock b1, BasicBlock b2 | + not b1 = b2.getImmediateDominator+() and b1.strictlyDominates(b2) + ) diff --git a/python/ql/test/library-tests/ControlFlow/dominators/idom.ql b/python/ql/test/library-tests/ControlFlow/dominators/idom.ql index 940624c6b20..cd948b6ff10 100644 --- a/python/ql/test/library-tests/ControlFlow/dominators/idom.ql +++ b/python/ql/test/library-tests/ControlFlow/dominators/idom.ql @@ -8,9 +8,8 @@ import python /* This query should *never* produce a result */ - from ControlFlowNode f -where not exists(f.getImmediateDominator()) -and not f.getNode() instanceof Scope +where + not exists(f.getImmediateDominator()) and + not f.getNode() instanceof Scope select f - diff --git a/python/ql/test/library-tests/ControlFlow/general/Comments.ql b/python/ql/test/library-tests/ControlFlow/general/Comments.ql index e93c8aae330..71d00f1a8d4 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Comments.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Comments.ql @@ -3,4 +3,3 @@ import python from Module m, int n where n = m.getMetrics().getNumberOfLinesOfComments() select m.toString(), n - diff --git a/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql b/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql index 6ca0327ab0b..fb801a29002 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql @@ -2,5 +2,3 @@ import python from Function func select func.toString(), func.getMetrics().getCyclomaticComplexity() - - diff --git a/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql b/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql index f038fd8d77a..66758604be2 100644 --- a/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql +++ b/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql @@ -1,16 +1,19 @@ - - import python -predicate -can_reach_from_entry_without_passing(ControlFlowNode target, ControlFlowNode pass) { - target != pass and target.getScope() = pass.getScope() and - (target.isEntryNode() or - exists(ControlFlowNode pre | target.getAPredecessor() = pre and can_reach_from_entry_without_passing(pre, pass))) +predicate can_reach_from_entry_without_passing(ControlFlowNode target, ControlFlowNode pass) { + target != pass and + target.getScope() = pass.getScope() and + ( + target.isEntryNode() + or + exists(ControlFlowNode pre | + target.getAPredecessor() = pre and can_reach_from_entry_without_passing(pre, pass) + ) + ) } from ControlFlowNode node, ControlFlowNode dom -where dom = node.getImmediateDominator() -and -can_reach_from_entry_without_passing(node, dom) +where + dom = node.getImmediateDominator() and + can_reach_from_entry_without_passing(node, dom) select node.toString(), dom.toString() diff --git a/python/ql/test/library-tests/ControlFlow/general/Lines.ql b/python/ql/test/library-tests/ControlFlow/general/Lines.ql index 60046ef3242..dabbe2bbf58 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Lines.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Lines.ql @@ -1,7 +1,8 @@ import python from Scope s, int n -where exists(Function f | f = s | n = f.getMetrics().getNumberOfLines()) or -exists(Module m | m = s | n = m.getMetrics().getNumberOfLines()) +where + exists(Function f | f = s | n = f.getMetrics().getNumberOfLines()) + or + exists(Module m | m = s | n = m.getMetrics().getNumberOfLines()) select s.toString(), n - diff --git a/python/ql/test/library-tests/ControlFlow/general/Reaches.ql b/python/ql/test/library-tests/ControlFlow/general/Reaches.ql index 548be578a76..3412e6a99bd 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Reaches.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Reaches.ql @@ -1,9 +1,8 @@ import python predicate reaches_exit(Name u) { - u.uses(_) and - exists(ControlFlowNode f, BasicBlock b | - f.getNode() = u and f.getBasicBlock() = b | + u.uses(_) and + exists(ControlFlowNode f, BasicBlock b | f.getNode() = u and f.getBasicBlock() = b | b.reachesExit() ) } diff --git a/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql b/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql index bfc884f7bac..35e43acaa12 100644 --- a/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql +++ b/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql @@ -6,12 +6,10 @@ import python from ControlFlowNode p, ControlFlowNode s, string kind -where p.getASuccessor() = s and -(if s = p.getAnExceptionalSuccessor() then - kind = "exception" - else - kind = " normal " -) and -not p.getNode() instanceof Scope and -not s.getNode() instanceof Scope -select p.getNode().getLocation().getStartLine(), p.toString(), kind, s.getNode().getLocation().getStartLine(), s +where + p.getASuccessor() = s and + (if s = p.getAnExceptionalSuccessor() then kind = "exception" else kind = " normal ") and + not p.getNode() instanceof Scope and + not s.getNode() instanceof Scope +select p.getNode().getLocation().getStartLine(), p.toString(), kind, + s.getNode().getLocation().getStartLine(), s diff --git a/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql b/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql index d9d5efbb494..c743952f2b1 100644 --- a/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql +++ b/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql @@ -1,8 +1,11 @@ import python from AstNode a, Scope s -where not a instanceof Import and not a instanceof If and not a instanceof AssignStmt and not a instanceof ExprStmt and -a.getScope() = s and -s instanceof Function -select -a.getLocation().getStartLine(), s.getName(), a, count(a.getAFlowNode()) +where + not a instanceof Import and + not a instanceof If and + not a instanceof AssignStmt and + not a instanceof ExprStmt and + a.getScope() = s and + s instanceof Function +select a.getLocation().getStartLine(), s.getName(), a, count(a.getAFlowNode()) diff --git a/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql b/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql index d865d9061c3..0941d2f2024 100644 --- a/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql +++ b/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql @@ -1,9 +1,8 @@ import python from ControlFlowNode p, Scope s -where -p.getScope() = s and -(exists (p.getATrueSuccessor()) or exists(p.getAFalseSuccessor())) and -s instanceof Function -select -p.getLocation().getStartLine(), s.getName(), p, strictcount(p.getASuccessor()) +where + p.getScope() = s and + (exists(p.getATrueSuccessor()) or exists(p.getAFalseSuccessor())) and + s instanceof Function +select p.getLocation().getStartLine(), s.getName(), p, strictcount(p.getASuccessor()) diff --git a/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql index c8ce2855455..d4cff3d6122 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql @@ -2,5 +2,5 @@ import python from SsaVariable var, SsaVariable def where def = var.getAnUltimateDefinition() -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), def, def.getLocation().getStartLine() +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + def, def.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql index b220553d07b..feafac5a6c7 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql @@ -1,14 +1,13 @@ import python - from SsaVariable v, string kind, ControlFlowNode use, int line -where use = v.getAUse() and -( - kind = "delete" and v.getDefinition().isDelete() - or - kind = "other " and not v.getDefinition().isDelete() -) -and line = use.getLocation().getStartLine() -and line != 0 - +where + use = v.getAUse() and + ( + kind = "delete" and v.getDefinition().isDelete() + or + kind = "other " and not v.getDefinition().isDelete() + ) and + line = use.getLocation().getStartLine() and + line != 0 select line, use.toString(), v.getId(), kind diff --git a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql index 5cfb210da24..fb2c8f20da8 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql @@ -2,6 +2,5 @@ import python from SsaVariable var, SsaVariable arg, BasicBlock pred where pred = var.getPredecessorBlockForPhiArgument(arg) -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), arg, arg.getLocation().getStartLine(), pred.getLastNode().getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + arg, arg.getLocation().getStartLine(), pred.getLastNode().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql index 6c4f617e172..a8aef8cc72d 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql @@ -2,6 +2,5 @@ import python from SsaVariable var, SsaVariable arg where arg = var.getAPhiInput() -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), arg, arg.getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + arg, arg.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql index df5df70d827..41b08ec0591 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql @@ -1,7 +1,5 @@ - import python from SsaVariable var where var.maybeUndefined() -select -var.getDefinition().getLocation().getStartLine(), var.toString() +select var.getDefinition().getLocation().getStartLine(), var.toString() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql index 9a3f4e92452..e120b6e1657 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql @@ -2,5 +2,5 @@ import python from ControlFlowNode use, SsaVariable def where def.getAUse() = use -select use.getLocation().getFile().getShortName(), -use.toString(), use.getLocation().getStartLine(), def.toString(), def.getLocation().getStartLine() +select use.getLocation().getFile().getShortName(), use.toString(), use.getLocation().getStartLine(), + def.toString(), def.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql index 5e2dd530ad9..1892974be9b 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql @@ -1,7 +1,4 @@ import python from SsaVariable var - -select var.getLocation().getFile().getShortName(), -var, var.getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var, var.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/successors/Successors.ql b/python/ql/test/library-tests/ControlFlow/successors/Successors.ql index 20567e057d1..802ed60962b 100644 --- a/python/ql/test/library-tests/ControlFlow/successors/Successors.ql +++ b/python/ql/test/library-tests/ControlFlow/successors/Successors.ql @@ -3,16 +3,15 @@ import semmle.python.TestUtils from ControlFlowNode p, ControlFlowNode s, string what where -s = p.getAFalseSuccessor() and what = "false" -or -s = p.getATrueSuccessor() and what = "true" -or -s = p.getAnExceptionalSuccessor() and what = "exceptional" -or -s = p.getANormalSuccessor() and what = "normal" -or -// Add fake edges for node that raise out of scope -p.isExceptionalExit(_) and s = p.getScope().getEntryNode() and what = "exit" - -select compact_location(p.getNode()), p.getNode().toString(), - compact_location(s.getNode()), s.getNode().toString(), what + s = p.getAFalseSuccessor() and what = "false" + or + s = p.getATrueSuccessor() and what = "true" + or + s = p.getAnExceptionalSuccessor() and what = "exceptional" + or + s = p.getANormalSuccessor() and what = "normal" + or + // Add fake edges for node that raise out of scope + p.isExceptionalExit(_) and s = p.getScope().getEntryNode() and what = "exit" +select compact_location(p.getNode()), p.getNode().toString(), compact_location(s.getNode()), + s.getNode().toString(), what diff --git a/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql b/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql index 163f57bcd06..352b1d2890d 100644 --- a/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql +++ b/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql @@ -9,8 +9,8 @@ import python from ControlFlowNode p, ControlFlowNode s where -s = p.getAnExceptionalSuccessor() -or -// Add fake edges for node that raise out of scope -p.isExceptionalExit(_) and s = p.getScope().getEntryNode() + s = p.getAnExceptionalSuccessor() + or + // Add fake edges for node that raise out of scope + p.isExceptionalExit(_) and s = p.getScope().getEntryNode() select p.getLocation().getFile().getShortName(), p.getLocation().getStartLine(), p, s.toString() diff --git a/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql b/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql index d5d8323a3a2..b2ca6cbd5ca 100644 --- a/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql +++ b/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql @@ -1,7 +1,5 @@ - - import python from ControlFlowNode f where f.getATrueSuccessor() = f.getAFalseSuccessor() -select f.toString() \ No newline at end of file +select f.toString() diff --git a/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql b/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql index 3320f06b8c7..1dedb90ea49 100644 --- a/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql +++ b/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql @@ -9,7 +9,8 @@ import python from ControlFlowNode p, ControlFlowNode s, string which where -s = p.getAFalseSuccessor() and which = "False" -or -s = p.getATrueSuccessor() and which = "True" -select p.getLocation().getFile().getShortName(), p.getLocation().getStartLine(), p, s.toString(), which + s = p.getAFalseSuccessor() and which = "False" + or + s = p.getATrueSuccessor() and which = "True" +select p.getLocation().getFile().getShortName(), p.getLocation().getStartLine(), p, s.toString(), + which diff --git a/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql b/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql index 8df422495fb..8ac7583b627 100644 --- a/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql +++ b/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql @@ -2,6 +2,5 @@ import python from SsaVariable var, ControlFlowNode use where use = var.getAUse() -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), use.toString(), use.getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + use.toString(), use.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/DefUse/Definitions.ql b/python/ql/test/library-tests/DefUse/Definitions.ql index 049bb7b9a82..52b00f42146 100644 --- a/python/ql/test/library-tests/DefUse/Definitions.ql +++ b/python/ql/test/library-tests/DefUse/Definitions.ql @@ -9,4 +9,4 @@ import python from Name d where d.defines(_) -select d.getId(), d.getLocation().getStartLine() \ No newline at end of file +select d.getId(), d.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/DefUse/Uses.ql b/python/ql/test/library-tests/DefUse/Uses.ql index bb02c6b5fac..ada93f740fb 100644 --- a/python/ql/test/library-tests/DefUse/Uses.ql +++ b/python/ql/test/library-tests/DefUse/Uses.ql @@ -9,4 +9,4 @@ import python from Name u where u.uses(_) -select u.getId(), u.getLocation().getStartLine() \ No newline at end of file +select u.getId(), u.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/DuplicateCode/Duplicate.ql b/python/ql/test/library-tests/DuplicateCode/Duplicate.ql index dfa9c11bf68..c680d481398 100644 --- a/python/ql/test/library-tests/DuplicateCode/Duplicate.ql +++ b/python/ql/test/library-tests/DuplicateCode/Duplicate.ql @@ -6,16 +6,18 @@ */ import python - import external.CodeDuplication predicate lexically_sorted(DuplicateBlock dup1, DuplicateBlock dup2) { - dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() - or - dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and dup1.sourceStartLine() < dup2.sourceStartLine() + dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() + or + dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and + dup1.sourceStartLine() < dup2.sourceStartLine() } from DuplicateBlock dup1, DuplicateBlock dup2 -where dup1.getEquivalenceClass() = dup2.getEquivalenceClass() -and lexically_sorted(dup1, dup2) -select dup1.toString(), dup2.toString(), dup1.sourceFile().getShortName(), dup1.sourceStartLine(), dup1.sourceEndLine() +where + dup1.getEquivalenceClass() = dup2.getEquivalenceClass() and + lexically_sorted(dup1, dup2) +select dup1.toString(), dup2.toString(), dup1.sourceFile().getShortName(), dup1.sourceStartLine(), + dup1.sourceEndLine() diff --git a/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql b/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql index a4243bca968..17904ea65cd 100644 --- a/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql +++ b/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql @@ -10,16 +10,17 @@ import external.CodeDuplication predicate mostlyDuplicateFunction(Function f) { exists(int covered, int total, Function other, int percent | - duplicateStatements(f, other, covered, total) and - covered != total and - total > 5 and - covered * 100 / total = percent and - percent > 80 and - not exists(Scope s | s = f.getScope*() | duplicateScopes(s, _, _, _)) + duplicateStatements(f, other, covered, total) and + covered != total and + total > 5 and + covered * 100 / total = percent and + percent > 80 and + not exists(Scope s | s = f.getScope*() | duplicateScopes(s, _, _, _)) ) } from Stmt s -where mostlyDuplicateFunction(s.getScope()) and -not duplicateStatement(s.getScope(), _, s, _) -select s.toString(), s.getLocation().toString() \ No newline at end of file +where + mostlyDuplicateFunction(s.getScope()) and + not duplicateStatement(s.getScope(), _, s, _) +select s.toString(), s.getLocation().toString() diff --git a/python/ql/test/library-tests/DuplicateCode/Similar.ql b/python/ql/test/library-tests/DuplicateCode/Similar.ql index 338ec5602ef..528908336d8 100644 --- a/python/ql/test/library-tests/DuplicateCode/Similar.ql +++ b/python/ql/test/library-tests/DuplicateCode/Similar.ql @@ -6,16 +6,17 @@ */ import python - import external.CodeDuplication predicate lexically_sorted(SimilarBlock dup1, SimilarBlock dup2) { - dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() - or - dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and dup1.sourceStartLine() < dup2.sourceStartLine() + dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() + or + dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and + dup1.sourceStartLine() < dup2.sourceStartLine() } from SimilarBlock dup1, SimilarBlock dup2 -where dup1.getEquivalenceClass() = dup2.getEquivalenceClass() -and lexically_sorted(dup1, dup2) +where + dup1.getEquivalenceClass() = dup2.getEquivalenceClass() and + lexically_sorted(dup1, dup2) select dup1, dup2, dup1.sourceFile().getShortName(), dup1.sourceStartLine(), dup1.sourceEndLine() diff --git a/python/ql/test/library-tests/PointsTo/absent/Absent.ql b/python/ql/test/library-tests/PointsTo/absent/Absent.ql index d21c2b339ae..95cdf3a1084 100644 --- a/python/ql/test/library-tests/PointsTo/absent/Absent.ql +++ b/python/ql/test/library-tests/PointsTo/absent/Absent.ql @@ -1,8 +1,6 @@ - import python import semmle.python.objects.Modules from Value val, ControlFlowNode f where f.pointsTo(val) select f, val - diff --git a/python/ql/test/library-tests/PointsTo/api/ClassValue.ql b/python/ql/test/library-tests/PointsTo/api/ClassValue.ql index 1c0c53d0bcd..a71380b7603 100644 --- a/python/ql/test/library-tests/PointsTo/api/ClassValue.ql +++ b/python/ql/test/library-tests/PointsTo/api/ClassValue.ql @@ -11,5 +11,4 @@ where cls = ClassValue::classmethod() and description = "classmethod" or cls = ClassValue::bool().getMro().getItem(2) and description = "object" - -select cls, description \ No newline at end of file +select cls, description diff --git a/python/ql/test/library-tests/PointsTo/api/Constants.ql b/python/ql/test/library-tests/PointsTo/api/Constants.ql index 73ff6750c4d..39763e6fc24 100644 --- a/python/ql/test/library-tests/PointsTo/api/Constants.ql +++ b/python/ql/test/library-tests/PointsTo/api/Constants.ql @@ -1,20 +1,16 @@ - import python from string txt, Value val where -exists(string s | - txt = "u'" + s + "'" and val = Value::forUnicode(s) + exists(string s | + txt = "u'" + s + "'" and val = Value::forUnicode(s) + or + txt = "b'" + s + "'" and val = Value::forBytes(s) + | + s = "a" or s = "b" or s = "c" or s = "d" + ) or - txt = "b'" + s + "'" and val = Value::forBytes(s) - | - s = "a" or s = "b" or s = "c" or s = "d" -) -or -exists(int i | - txt = i.toString() and val = Value::forInt(i) - | - i in [1..10] or i in [1000..1010] -) - + exists(int i | txt = i.toString() and val = Value::forInt(i) | + i in [1 .. 10] or i in [1000 .. 1010] + ) select txt, val diff --git a/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql b/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql index 8c82e2d106f..226b2520521 100644 --- a/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql +++ b/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql @@ -1,16 +1,15 @@ - import python from FunctionValue v, string name -where name = v.getQualifiedName() and -( - v = Value::named("len") - or - v instanceof PythonFunctionValue - or - v = Value::named("sys.exit") - or - v = Value::named("list").(ClassValue).lookup("append") -) - -select v, name \ No newline at end of file +where + name = v.getQualifiedName() and + ( + v = Value::named("len") + or + v instanceof PythonFunctionValue + or + v = Value::named("sys.exit") + or + v = Value::named("list").(ClassValue).lookup("append") + ) +select v, name diff --git a/python/ql/test/library-tests/PointsTo/api/Value.ql b/python/ql/test/library-tests/PointsTo/api/Value.ql index 674dce5a299..23d78317764 100644 --- a/python/ql/test/library-tests/PointsTo/api/Value.ql +++ b/python/ql/test/library-tests/PointsTo/api/Value.ql @@ -2,11 +2,12 @@ import python from Value val, string name where - val = Value::named(name) - and + val = Value::named(name) and ( - name = "bool" or name = "sys" or name = "sys.argv" or - name = "ValueError" or name = "slice" + name = "bool" or + name = "sys" or + name = "sys.argv" or + name = "ValueError" or + name = "slice" ) - -select val, name \ No newline at end of file +select val, name diff --git a/python/ql/test/library-tests/PointsTo/calls/Argument.ql b/python/ql/test/library-tests/PointsTo/calls/Argument.ql index e88baf75791..1678c02c182 100644 --- a/python/ql/test/library-tests/PointsTo/calls/Argument.ql +++ b/python/ql/test/library-tests/PointsTo/calls/Argument.ql @@ -2,4 +2,4 @@ import python from ControlFlowNode arg, FunctionObject func, int i where arg = func.getArgumentForCall(_, i) -select arg.getLocation().getStartLine(), i, arg.toString(), func.toString() \ No newline at end of file +select arg.getLocation().getStartLine(), i, arg.toString(), func.toString() diff --git a/python/ql/test/library-tests/PointsTo/calls/Call.ql b/python/ql/test/library-tests/PointsTo/calls/Call.ql index d1cfbdad690..94c4212cc64 100644 --- a/python/ql/test/library-tests/PointsTo/calls/Call.ql +++ b/python/ql/test/library-tests/PointsTo/calls/Call.ql @@ -1,7 +1,5 @@ - import python from ControlFlowNode call, FunctionObject func - where call = func.getACall() -select call.getLocation().getStartLine(), call.toString(), func.toString() \ No newline at end of file +select call.getLocation().getStartLine(), call.toString(), func.toString() diff --git a/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql b/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql index 804ae3a61df..958306c53e6 100644 --- a/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql @@ -1,4 +1,3 @@ - import python import semmle.python.objects.ObjectAPI diff --git a/python/ql/test/library-tests/PointsTo/customise/test.ql b/python/ql/test/library-tests/PointsTo/customise/test.ql index dca091e2e4f..8aea8b05b18 100644 --- a/python/ql/test/library-tests/PointsTo/customise/test.ql +++ b/python/ql/test/library-tests/PointsTo/customise/test.ql @@ -1,15 +1,15 @@ - import python import semmle.python.types.Extensions -/* Customise: Claim any function called has_type_XXX return any class +/* + * Customise: Claim any function called has_type_XXX return any class * whose name matches XXX */ -class HasTypeFact extends CustomPointsToOriginFact { +class HasTypeFact extends CustomPointsToOriginFact { HasTypeFact() { exists(FunctionObject func, string name | - func.getACall() = this and + func.getACall() = this and name = func.getName() and name.prefix("has_type_".length()) = "has_type_" ) @@ -17,19 +17,19 @@ class HasTypeFact extends CustomPointsToOriginFact { override predicate pointsTo(Object value, ClassObject cls) { exists(FunctionObject func, string name | - func.getACall() = this and + func.getACall() = this and name = func.getName() and - name.prefix("has_type_".length()) = "has_type_" | + name.prefix("has_type_".length()) = "has_type_" + | cls.getName() = name.suffix("has_type_".length()) ) and value = this } - } - from int line, ControlFlowNode f, Object o, ClassObject c -where f.getLocation().getStartLine() = line and - exists(Comment ct | ct.getLocation().getStartLine() < line) and - f.refersTo(o, c, _) +where + f.getLocation().getStartLine() = line and + exists(Comment ct | ct.getLocation().getStartLine() < line) and + f.refersTo(o, c, _) select line, f.toString(), o.toString(), c.toString() diff --git a/python/ql/test/library-tests/PointsTo/decorators/Test.ql b/python/ql/test/library-tests/PointsTo/decorators/Test.ql index af274849a26..3aff12a3a1f 100644 --- a/python/ql/test/library-tests/PointsTo/decorators/Test.ql +++ b/python/ql/test/library-tests/PointsTo/decorators/Test.ql @@ -3,9 +3,8 @@ import python // We don't care about the internals of functools which vary from // version to version, just the end result. from NameNode f, Object o, ControlFlowNode x, int line - -where f.refersTo(o, x) and -f.getLocation().getFile().getBaseName() = "test.py" and -line = f.getLocation().getStartLine() - +where + f.refersTo(o, x) and + f.getLocation().getFile().getBaseName() = "test.py" and + line = f.getLocation().getStartLine() select line, f.toString(), o.toString(), x.getLocation().toString() diff --git a/python/ql/test/library-tests/PointsTo/decorators/Values.ql b/python/ql/test/library-tests/PointsTo/decorators/Values.ql index 2e752466c55..712cc025786 100644 --- a/python/ql/test/library-tests/PointsTo/decorators/Values.ql +++ b/python/ql/test/library-tests/PointsTo/decorators/Values.ql @@ -1,10 +1,9 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from NameNode f, Context ctx, ObjectInternal v where - f.getLocation().getFile().getBaseName() = "test.py" and - PointsTo::pointsTo(f, ctx, v, _) + f.getLocation().getFile().getBaseName() = "test.py" and + PointsTo::pointsTo(f, ctx, v, _) select f, ctx, v diff --git a/python/ql/test/library-tests/PointsTo/extensions/Extend.ql b/python/ql/test/library-tests/PointsTo/extensions/Extend.ql index af4a696ea4f..14082905ce4 100644 --- a/python/ql/test/library-tests/PointsTo/extensions/Extend.ql +++ b/python/ql/test/library-tests/PointsTo/extensions/Extend.ql @@ -1,13 +1,8 @@ - - import python - import semmle.python.pointsto.PointsTo private import semmle.python.types.Extensions - class CfgExtension extends CustomPointsToOriginFact { - CfgExtension() { this.(NameNode).getId() = "one" or @@ -24,23 +19,23 @@ class CfgExtension extends CustomPointsToOriginFact { } } -class AttributeExtension extends CustomPointsToAttribute { - +class AttributeExtension extends CustomPointsToAttribute { AttributeExtension() { this = this } - override predicate attributePointsTo(string name, Object value, ClassObject cls, ControlFlowNode origin) { - cls = theIntType() and origin = any(Module m).getEntryNode() and + override predicate attributePointsTo( + string name, Object value, ClassObject cls, ControlFlowNode origin + ) { + cls = theIntType() and + origin = any(Module m).getEntryNode() and ( name = "three" and value.(NumericObject).intValue() = 3 or name = "four" and value.(NumericObject).intValue() = 4 ) } - } class NoClassExtension extends CustomPointsToObjectFact { - NoClassExtension() { this = this } override predicate pointsTo(Object value) { @@ -48,24 +43,17 @@ class NoClassExtension extends CustomPointsToObjectFact { or this.(NameNode).getId() = "six" and value.(NumericObject).intValue() = 6 } - } /* Check that we can use old API without causing non-monotonic recursion */ class RecurseIntoOldPointsTo extends CustomPointsToOriginFact { - - RecurseIntoOldPointsTo() { - PointsTo::points_to(this, _, unknownValue(), _, _) - } + RecurseIntoOldPointsTo() { PointsTo::points_to(this, _, unknownValue(), _, _) } override predicate pointsTo(Object value, ClassObject cls) { value = unknownValue() and cls = theUnknownType() } } - from ControlFlowNode f, Object o where f.getLocation().getFile().getBaseName() = "test.py" and f.refersTo(o) select f, o.toString() - - diff --git a/python/ql/test/library-tests/PointsTo/functions/Calls.ql b/python/ql/test/library-tests/PointsTo/functions/Calls.ql index 6f1e8cf8bd3..2833c2e60be 100644 --- a/python/ql/test/library-tests/PointsTo/functions/Calls.ql +++ b/python/ql/test/library-tests/PointsTo/functions/Calls.ql @@ -1,12 +1,11 @@ - import python from CallNode call, FunctionObject func, string kind -where -(func.getAMethodCall() = call and kind = "method" - or - func.getAFunctionCall() = call and kind = "function" -) -and -call.getLocation().getFile().getShortName().matches("odasa%") +where + ( + func.getAMethodCall() = call and kind = "method" + or + func.getAFunctionCall() = call and kind = "function" + ) and + call.getLocation().getFile().getShortName().matches("odasa%") select call.getLocation().getStartLine(), call.toString(), func.toString(), kind diff --git a/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql b/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql index ebb69fc7a0f..c576651a8e6 100644 --- a/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql +++ b/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql @@ -1,4 +1,3 @@ - import python from FunctionObject f diff --git a/python/ql/test/library-tests/PointsTo/functions/test.ql b/python/ql/test/library-tests/PointsTo/functions/test.ql index dd1a070d99f..f520f6b2254 100644 --- a/python/ql/test/library-tests/PointsTo/functions/test.ql +++ b/python/ql/test/library-tests/PointsTo/functions/test.ql @@ -1,9 +1,7 @@ import python from Call c, FunctionObject f - -where c.getFunc().(Attribute).getObject().(Name).getId() = "self" -and -f.getACall().getNode() = c - +where + c.getFunc().(Attribute).getObject().(Name).getId() = "self" and + f.getACall().getNode() = c select c.getLocation().getStartLine(), f.toString() diff --git a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql index 147b7835e24..a7b9403a18d 100644 --- a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql @@ -1,10 +1,9 @@ - import python import interesting from int line, ControlFlowNode f, Object o, ImportTimeScope n -where -of_interest(f, line) and -f.refersTo(o) and -f.getScope() = n +where + of_interest(f, line) and + f.refersTo(o) and + f.getScope() = n select n.toString(), line, f.toString(), o.toString() diff --git a/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql b/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql index 00144c87601..342a329746e 100644 --- a/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql @@ -10,7 +10,7 @@ import interesting import Util from int line, ControlFlowNode f, Object o -where - of_interest(f, line) and - f.refersTo(o) +where + of_interest(f, line) and + f.refersTo(o) select line, f.toString(), repr(o) diff --git a/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql b/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql index 693d0b2b84b..c80de106c3d 100644 --- a/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql +++ b/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql @@ -1,10 +1,9 @@ - import python import interesting import Util from int line, ControlFlowNode f, Object o, ClassObject cls -where - of_interest(f, line) and - f.refersTo(o, cls, _) +where + of_interest(f, line) and + f.refersTo(o, cls, _) select line, f.toString(), repr(o), repr(cls) diff --git a/python/ql/test/library-tests/PointsTo/global/Global.ql b/python/ql/test/library-tests/PointsTo/global/Global.ql index 8aa0453645f..d9b8a246d11 100644 --- a/python/ql/test/library-tests/PointsTo/global/Global.ql +++ b/python/ql/test/library-tests/PointsTo/global/Global.ql @@ -1,14 +1,11 @@ - import python - - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext import semmle.python.objects.ObjectInternal from ControlFlowNode f, PointsToContext ctx, Value obj, ControlFlowNode orig -where exists(ExprStmt s | s.getValue().getAFlowNode() = f) and -PointsTo::pointsTo(f, ctx, obj, orig) - +where + exists(ExprStmt s | s.getValue().getAFlowNode() = f) and + PointsTo::pointsTo(f, ctx, obj, orig) select ctx, f, obj.toString(), orig diff --git a/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql b/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql index 98644b02e99..b545f6e6a18 100644 --- a/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql @@ -1,7 +1,8 @@ import python from ControlFlowNode f, Object o, ControlFlowNode x - -where f.refersTo(o, x) and exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) - -select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine() +where + f.refersTo(o, x) and + exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) +select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), + o.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql b/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql index 83bbd5e42ba..2bf6b6b62a9 100644 --- a/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql +++ b/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql @@ -1,7 +1,8 @@ import python from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - -where f.refersTo(o, c, x) and exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) - -select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), x.getLocation().getStartLine() +where + f.refersTo(o, c, x) and + exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) +select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), + o.toString(), c.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/import_star/Values.ql b/python/ql/test/library-tests/PointsTo/import_star/Values.ql index f5bfe1bfeac..b54b8c6c78d 100644 --- a/python/ql/test/library-tests/PointsTo/import_star/Values.ql +++ b/python/ql/test/library-tests/PointsTo/import_star/Values.ql @@ -1,7 +1,5 @@ - import python from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin -where - f.pointsTo(ctx, v, origin) +where f.pointsTo(ctx, v, origin) select f, ctx, v diff --git a/python/ql/test/library-tests/PointsTo/imports/Runtime.ql b/python/ql/test/library-tests/PointsTo/imports/Runtime.ql index 4a25bff744a..4d917aa5af6 100644 --- a/python/ql/test/library-tests/PointsTo/imports/Runtime.ql +++ b/python/ql/test/library-tests/PointsTo/imports/Runtime.ql @@ -1,8 +1,9 @@ - import python from int line, ControlFlowNode f, Object o, ControlFlowNode orig -where - not f.getLocation().getFile().inStdlib() and - f.refersTo(o, orig) and line = f.getLocation().getStartLine() and line != 0 +where + not f.getLocation().getFile().inStdlib() and + f.refersTo(o, orig) and + line = f.getLocation().getStartLine() and + line != 0 select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), orig.toString() diff --git a/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql b/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql index eca5e965ea8..7e915d04573 100644 --- a/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql +++ b/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql @@ -1,8 +1,10 @@ - import python from int line, ControlFlowNode f, Object o, ClassObject cls, ControlFlowNode orig -where - not f.getLocation().getFile().inStdlib() and - f.refersTo(o, cls, orig) and line = f.getLocation().getStartLine() and line != 0 -select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), cls.toString(), orig.toString() +where + not f.getLocation().getFile().inStdlib() and + f.refersTo(o, cls, orig) and + line = f.getLocation().getStartLine() and + line != 0 +select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), cls.toString(), + orig.toString() diff --git a/python/ql/test/library-tests/PointsTo/indexing/Test.ql b/python/ql/test/library-tests/PointsTo/indexing/Test.ql index 70b62e825f7..825cb1cf3be 100644 --- a/python/ql/test/library-tests/PointsTo/indexing/Test.ql +++ b/python/ql/test/library-tests/PointsTo/indexing/Test.ql @@ -1,8 +1,7 @@ import python from ControlFlowNode f, Object o, ControlFlowNode x - -where f.refersTo(o, x) and -f.getLocation().getFile().getBaseName() = "test.py" - +where + f.refersTo(o, x) and + f.getLocation().getFile().getBaseName() = "test.py" select f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql b/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql index 6b0c8b8460d..e11999a75de 100644 --- a/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql +++ b/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql @@ -1,8 +1,8 @@ import python from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - -where f.refersTo(o, c, x) and -f.getLocation().getFile().getBaseName() = "test.py" - -select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), x.getLocation().getStartLine() +where + f.refersTo(o, c, x) and + f.getLocation().getFile().getBaseName() = "test.py" +select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), + x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql b/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql index 27b2ed4ce2f..c4677b7df51 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql @@ -1,7 +1,7 @@ - import python from ClassObject cls, ClassObject base, int n -where not cls.isBuiltin() and -base = cls.getBaseType(n) +where + not cls.isBuiltin() and + base = cls.getBaseType(n) select cls.toString(), n, base.toString() diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql b/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql index d35ac04bb30..f91d207fc70 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql @@ -1,8 +1,5 @@ - import python from Call c, FunctionObject f - where f.getACall().getNode() = c - select c.getLocation().getStartLine(), f.toString(), f.getFunction().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql b/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql index aefdb8894bd..def579bb22d 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql b/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql index ee837e66478..be4d9ef5711 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.Base diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql b/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql index bf020de465b..13d3eece75f 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal diff --git a/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql b/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql index 064cc2ca688..3768116ff11 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql @@ -1,8 +1,7 @@ - import python from ClassObject cls, ClassObject meta -where not cls.isBuiltin() and -meta = cls.getMetaClass() +where + not cls.isBuiltin() and + meta = cls.getMetaClass() select cls.toString(), meta.toString() - diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql b/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql index 38767957493..7fdd431c216 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql @@ -1,14 +1,10 @@ - import python - private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo /** Make unknown type visible */ class UnknownType extends UnknownClassInternal { - override string toString() { result = "*UNKNOWN TYPE" } - } from ClassObjectInternal c diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Self.ql b/python/ql/test/library-tests/PointsTo/inheritance/Self.ql index a72da5f5248..050690fd1cb 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Self.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Self.ql @@ -1,4 +1,3 @@ - import python from NameNode n, Object value, ClassObject cls diff --git a/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql b/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql index 0793957f2e4..7810c607787 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql @@ -1,7 +1,7 @@ - import python from ClassObject cls, ClassObject sup -where not cls.isBuiltin() and -sup = cls.getASuperType() +where + not cls.isBuiltin() and + sup = cls.getASuperType() select cls.toString(), sup.toString() diff --git a/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql b/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql index d3cde3b0771..996b8597d5e 100644 --- a/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql @@ -1,10 +1,9 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from ControlFlowNode f, ObjectInternal obj, ControlFlowNode orig -where exists(ExprStmt s | s.getValue().getAFlowNode() = f) and -PointsTo::pointsTo(f, _, obj, orig) - +where + exists(ExprStmt s | s.getValue().getAFlowNode() = f) and + PointsTo::pointsTo(f, _, obj, orig) select f, obj.toString(), orig diff --git a/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql b/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql index febbda03f03..67aff9597c2 100644 --- a/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql +++ b/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql @@ -1,12 +1,13 @@ import python from string l, NameNode n -where n.getLocation().getFile().getShortName() = "test.py" and -( - n.isGlobal() and l = "global" - or - n.isLocal() and l = "local" - or - n.isNonLocal() and l = "non-local" -) +where + n.getLocation().getFile().getShortName() = "test.py" and + ( + n.isGlobal() and l = "global" + or + n.isLocal() and l = "local" + or + n.isNonLocal() and l = "non-local" + ) select n.getLocation().getStartLine(), n.getId(), l diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql b/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql index 4fe75b70572..d9cb2f019a6 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql @@ -1,9 +1,7 @@ - import python from ClassObject cls, string reason - -where cls.getPyClass().getEnclosingModule().getName() = "test" -and cls.failedInference(reason) - +where + cls.getPyClass().getEnclosingModule().getName() = "test" and + cls.failedInference(reason) select cls, reason diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql b/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql index ec3257a8627..5a10701ef83 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql @@ -1,14 +1,10 @@ - import python - private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo /** Make unknown type visible */ class UnknownType extends UnknownClassInternal { - override string toString() { result = "*UNKNOWN TYPE" } - } from PythonClassObjectInternal cls diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Style.ql b/python/ql/test/library-tests/PointsTo/metaclass/Style.ql index 8c5d6913e15..29feef64ec1 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Style.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Style.ql @@ -1,13 +1,11 @@ - - import python - from ClassObject cls, string style -where cls.getPyClass().getEnclosingModule().getName() = "test" -and ( - cls.isNewStyle() and style = "new" - or - cls.isOldStyle() and style = "old" -) +where + cls.getPyClass().getEnclosingModule().getName() = "test" and + ( + cls.isNewStyle() and style = "new" + or + cls.isOldStyle() and style = "old" + ) select cls, style diff --git a/python/ql/test/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/library-tests/PointsTo/metaclass/test.ql index 5b80203e60f..17b90483315 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/test.ql @@ -1,12 +1,9 @@ - import python private import semmle.python.objects.ObjectInternal /** Make unknown type visible */ class UnknownType extends UnknownClassInternal { - override string toString() { result = "*UNKNOWN TYPE" } - } from ClassObject cls diff --git a/python/ql/test/library-tests/PointsTo/new/Call.ql b/python/ql/test/library-tests/PointsTo/new/Call.ql index f740b0060f6..f014001f315 100644 --- a/python/ql/test/library-tests/PointsTo/new/Call.ql +++ b/python/ql/test/library-tests/PointsTo/new/Call.ql @@ -1,8 +1,6 @@ - import python import Util from ControlFlowNode call, FunctionObject func - where call = func.getACall() -select locate(call.getLocation(), "abdglq"), call.toString(), func.getQualifiedName() \ No newline at end of file +select locate(call.getLocation(), "abdglq"), call.toString(), func.getQualifiedName() diff --git a/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql b/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql index 2d13f2ae851..5ad6fabd380 100644 --- a/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql +++ b/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql @@ -1,9 +1,8 @@ - import python import semmle.python.types.Descriptors import Util from ClassMethodObject cm, CallNode call where call = cm.getACall() -select locate(call.getLocation(), "lp"), cm.getFunction().toString(), cm.(ControlFlowNode).getLocation().toString() - +select locate(call.getLocation(), "lp"), cm.getFunction().toString(), + cm.(ControlFlowNode).getLocation().toString() diff --git a/python/ql/test/library-tests/PointsTo/new/Dataflow.ql b/python/ql/test/library-tests/PointsTo/new/Dataflow.ql index c2ed05aa9dc..47a12acee53 100755 --- a/python/ql/test/library-tests/PointsTo/new/Dataflow.ql +++ b/python/ql/test/library-tests/PointsTo/new/Dataflow.ql @@ -1,8 +1,7 @@ - - import python import Util from EssaVariable v, EssaDefinition def where def = v.getDefinition() and not v.getSourceVariable() instanceof SpecialSsaSourceVariable -select locate(def.getLocation(), "abdefghijknrs_"), v.getRepresentation() + " = " + def.getRepresentation() +select locate(def.getLocation(), "abdefghijknrs_"), + v.getRepresentation() + " = " + def.getRepresentation() diff --git a/python/ql/test/library-tests/PointsTo/new/Definitions.ql b/python/ql/test/library-tests/PointsTo/new/Definitions.ql index dbaac3b09f9..5abcb663e16 100644 --- a/python/ql/test/library-tests/PointsTo/new/Definitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/Definitions.ql @@ -1,8 +1,6 @@ - import python - import Util from EssaDefinition def, Variable v where v = def.getSourceVariable() and not v instanceof SpecialSsaSourceVariable -select locate(def.getLocation(), "abdgk"), v.toString(), def.getAQlClass() \ No newline at end of file +select locate(def.getLocation(), "abdgk"), v.toString(), def.getAQlClass() diff --git a/python/ql/test/library-tests/PointsTo/new/Live.ql b/python/ql/test/library-tests/PointsTo/new/Live.ql index 51f2b4e04a7..4bcb7da27e6 100644 --- a/python/ql/test/library-tests/PointsTo/new/Live.ql +++ b/python/ql/test/library-tests/PointsTo/new/Live.ql @@ -1,14 +1,10 @@ - import python import semmle.python.essa.SsaCompute - import Util from Variable var, BasicBlock b, ControlFlowNode loc, string end where -Liveness::liveAtEntry(var, b) and end = "entry" and loc = b.getNode(0) -or -Liveness::liveAtExit(var, b) and end = "exit" and loc = b.getLastNode() - - -select var, locate(loc.getLocation(), "b"), end \ No newline at end of file + Liveness::liveAtEntry(var, b) and end = "entry" and loc = b.getNode(0) + or + Liveness::liveAtExit(var, b) and end = "exit" and loc = b.getLastNode() +select var, locate(loc.getLocation(), "b"), end diff --git a/python/ql/test/library-tests/PointsTo/new/NameSpace.ql b/python/ql/test/library-tests/PointsTo/new/NameSpace.ql index 4e30796dc0b..18fd5e9e37c 100644 --- a/python/ql/test/library-tests/PointsTo/new/NameSpace.ql +++ b/python/ql/test/library-tests/PointsTo/new/NameSpace.ql @@ -2,17 +2,17 @@ import python import Util from Scope s, string name, Object val -where name != "__name__" and -( - exists(ModuleObject m | - m.getModule() = s and - m.attributeRefersTo(name, val, _) - ) - or - exists(ClassObject cls | - cls.getPyClass() = s and - cls.declaredAttribute(name) = val - ) -) - -select locate(s.getLocation(), "abcdghijklopqrs"), s.toString(), name, repr(val) \ No newline at end of file +where + name != "__name__" and + ( + exists(ModuleObject m | + m.getModule() = s and + m.attributeRefersTo(name, val, _) + ) + or + exists(ClassObject cls | + cls.getPyClass() = s and + cls.declaredAttribute(name) = val + ) + ) +select locate(s.getLocation(), "abcdghijklopqrs"), s.toString(), name, repr(val) diff --git a/python/ql/test/library-tests/PointsTo/new/Parameters.ql b/python/ql/test/library-tests/PointsTo/new/Parameters.ql index e3a76f9dc70..50c08a6fa0d 100644 --- a/python/ql/test/library-tests/PointsTo/new/Parameters.ql +++ b/python/ql/test/library-tests/PointsTo/new/Parameters.ql @@ -1,10 +1,6 @@ - import python - import Util from ParameterDefinition param, boolean self -where -if param.isSelf() then self = true else self = false - +where if param.isSelf() then self = true else self = false select locate(param.getLocation(), "g"), param.toString(), self diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql b/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql index 341c6f28745..044d33c2887 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql @@ -4,7 +4,6 @@ import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal /* This test should return _no_ results. */ - predicate relevant_node(ControlFlowNode n) { exists(CallNode c | c.getFunction().(NameNode).getId() = "check" and @@ -14,8 +13,8 @@ predicate relevant_node(ControlFlowNode n) { exists(Comment c, string filepath, int bl | n.getNode().getScope().getLocation().hasLocationInfo(filepath, bl, _, _, _) and c.getLocation().hasLocationInfo(filepath, bl, _, _, _) and - c.getText().matches("%check") - and not n.(NameNode).isStore() + c.getText().matches("%check") and + not n.(NameNode).isStore() ) } diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql b/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql index 3bebd98bff1..c5009ad4cb6 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql @@ -2,8 +2,5 @@ import python import Util from ControlFlowNode f, ControlFlowNode x - -where -f.refersTo(theNoneObject(), _, x) - +where f.refersTo(theNoneObject(), _, x) select locate(f.getLocation(), "abcdghijklmopqr"), f.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql b/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql index 9c9c432717f..27ebf200ee2 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql @@ -4,7 +4,5 @@ import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from ControlFlowNode f, ControlFlowNode x - where PointsTo::pointsTo(f, _, ObjectInternal::unknown(), x) - select locate(f.getLocation(), "abchr"), f.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql index e2ef1fc3c61..56a58642f1c 100755 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql @@ -4,7 +4,6 @@ import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x, PointsToContext ctx - where PointsTo::points_to(f, ctx, o, c, x) - -select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), repr(o), repr(c), x.getLocation().getStartLine(), ctx +select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), repr(o), repr(c), + x.getLocation().getStartLine(), ctx diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql index 0c845f6bc3c..ed04a0b3dc3 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql @@ -3,7 +3,6 @@ import Util import semmle.python.pointsto.PointsTo from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - where PointsTo::points_to(f, _, o, c, x) - -select locate(f.getLocation(), "abdeghijkls"), f.toString(), repr(o), repr(c), x.getLocation().getStartLine() +select locate(f.getLocation(), "abdeghijkls"), f.toString(), repr(o), repr(c), + x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/new/Precedes.ql b/python/ql/test/library-tests/PointsTo/new/Precedes.ql index 959ec181f5f..bda245eca6d 100644 --- a/python/ql/test/library-tests/PointsTo/new/Precedes.ql +++ b/python/ql/test/library-tests/PointsTo/new/Precedes.ql @@ -1,8 +1,7 @@ - import python import Util from Scope pre, Scope post where pre.precedes(post) - -select locate(pre.getLocation(), "q"), pre.toString(), locate(post.getLocation(), "q"), post.toString() +select locate(pre.getLocation(), "q"), pre.toString(), locate(post.getLocation(), "q"), + post.toString() diff --git a/python/ql/test/library-tests/PointsTo/new/Reachable.ql b/python/ql/test/library-tests/PointsTo/new/Reachable.ql index 577d724c8e6..f8b2f0585eb 100644 --- a/python/ql/test/library-tests/PointsTo/new/Reachable.ql +++ b/python/ql/test/library-tests/PointsTo/new/Reachable.ql @@ -1,4 +1,3 @@ - import python private import semmle.python.pointsto.PointsTo import Util diff --git a/python/ql/test/library-tests/PointsTo/new/SSA.ql b/python/ql/test/library-tests/PointsTo/new/SSA.ql index 6c30a5f031f..6c154f57e57 100644 --- a/python/ql/test/library-tests/PointsTo/new/SSA.ql +++ b/python/ql/test/library-tests/PointsTo/new/SSA.ql @@ -1,11 +1,12 @@ - import python private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext import Util from EssaVariable v, EssaDefinition def, Object o, ClassObject cls -where def = v.getDefinition() and -not v.getSourceVariable() instanceof SpecialSsaSourceVariable and -PointsTo::ssa_variable_points_to(v, _, o, cls, _) -select locate(def.getLocation(), "abcdegjqmns_"), v.getRepresentation() + " = " + def.getRepresentation(), repr(o), repr(cls) +where + def = v.getDefinition() and + not v.getSourceVariable() instanceof SpecialSsaSourceVariable and + PointsTo::ssa_variable_points_to(v, _, o, cls, _) +select locate(def.getLocation(), "abcdegjqmns_"), + v.getRepresentation() + " = " + def.getRepresentation(), repr(o), repr(cls) diff --git a/python/ql/test/library-tests/PointsTo/new/Sanity.ql b/python/ql/test/library-tests/PointsTo/new/Sanity.ql index 5559354362c..8c3347f6682 100644 --- a/python/ql/test/library-tests/PointsTo/new/Sanity.ql +++ b/python/ql/test/library-tests/PointsTo/new/Sanity.ql @@ -1,98 +1,119 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal predicate ssa_sanity(string clsname, string problem, string what) { /* Exactly one definition of each SSA variable */ - exists(EssaVariable var | - clsname = var.getAQlClass() | + exists(EssaVariable var | clsname = var.getAQlClass() | /* Exactly one definition of each SSA variable */ - count(var.getDefinition()) != 1 and problem = " has " + count(var.getDefinition()) + " definitions." and + count(var.getDefinition()) != 1 and + problem = " has " + count(var.getDefinition()) + " definitions." and what = "SSA variable " + var.getSourceVariable().getName() or /* Backing variable */ - not exists(var.getSourceVariable()) and problem = "An SSA variable has no backing variable." and + not exists(var.getSourceVariable()) and + problem = "An SSA variable has no backing variable." and what = "An SSA variable" or - count(var.getSourceVariable()) != 1 and problem = var.getSourceVariable().getName() + " has " + count(var.getSourceVariable()) + " backing variables." and + count(var.getSourceVariable()) != 1 and + problem = + var.getSourceVariable().getName() + " has " + count(var.getSourceVariable()) + + " backing variables." and what = "SSA variable " + var.getSourceVariable().getName() ) or /* Exactly one location */ exists(EssaDefinition def | clsname = def.getAQlClass() and - what = "SSA Definition " + def.getSourceVariable().getName() + " in " + def.getSourceVariable().(Variable).getScope().getName() and - count(def.getLocation()) != 1 and problem = " has " + count(def.getLocation()) + " locations" + what = + "SSA Definition " + def.getSourceVariable().getName() + " in " + + def.getSourceVariable().(Variable).getScope().getName() and + count(def.getLocation()) != 1 and + problem = " has " + count(def.getLocation()) + " locations" ) or /* Must have a source variable */ exists(EssaDefinition def | clsname = def.getAQlClass() and not exists(def.getSourceVariable()) and - what = " at " + def.getLocation() and + what = " at " + def.getLocation() and problem = "has not source variable" ) - or + or /* Variables must have exactly one representation */ exists(EssaVariable var | clsname = var.getAQlClass() and - what = "SSA variable " + var.getSourceVariable().getName() + " defined at " + var.getDefinition().getLocation() and - count(var.getRepresentation()) != 1 and problem = " has " + count(var.getRepresentation()) + " representations" + what = + "SSA variable " + var.getSourceVariable().getName() + " defined at " + + var.getDefinition().getLocation() and + count(var.getRepresentation()) != 1 and + problem = " has " + count(var.getRepresentation()) + " representations" ) or /* Definitions must have exactly one representation */ exists(EssaDefinition def | clsname = def.getAQlClass() and what = "SSA definition " + def.getSourceVariable().getName() + " at " + def.getLocation() and - count(def.getRepresentation()) != 1 and problem = " has " + count(def.getRepresentation()) + " representations: " + def.getRepresentation() + count(def.getRepresentation()) != 1 and + problem = + " has " + count(def.getRepresentation()) + " representations: " + def.getRepresentation() ) or /* Refinements must have exactly one input */ exists(EssaNodeRefinement ref | clsname = ref.getAQlClass() and what = "Refinement " + ref.getSourceVariable().getName() + " at " + ref.getLocation() and - count(ref.getInput()) != 1 and problem = " has " + count(ref.getInput()) + " inputs: " + ref.getInput().getRepresentation() + count(ref.getInput()) != 1 and + problem = " has " + count(ref.getInput()) + " inputs: " + ref.getInput().getRepresentation() ) or - /* Ideally filter nodes should have exactly one input, but it is not a big deal - * if we prune away the input, leaving it with none. */ + /* + * Ideally filter nodes should have exactly one input, but it is not a big deal + * if we prune away the input, leaving it with none. + */ + exists(EssaEdgeRefinement def | clsname = def.getAQlClass() and - what = def.getSourceVariable().getName() + " at " + def.getLocation() | - count(def.getInput()) > 1 and problem =" has " + count(def.getInput()) + " inputs." + what = def.getSourceVariable().getName() + " at " + def.getLocation() + | + count(def.getInput()) > 1 and problem = " has " + count(def.getInput()) + " inputs." ) or /* Each use has only one reaching SSA variable */ exists(ControlFlowNode use, SsaSourceVariable v, int c | c = strictcount(EssaVariable s | s.getAUse() = use and s.getSourceVariable() = v) and - clsname = use.getAQlClass() and c != 1 and - what = use + " at " + use.getLocation() and - problem =" has " + c + " SSA variables reaching." + clsname = use.getAQlClass() and + c != 1 and + what = use + " at " + use.getLocation() and + problem = " has " + c + " SSA variables reaching." ) or /* Python-specific subclasses of EssaDefinitions should be disjoint and complete */ exists(EssaDefinition def | clsname = def.getAQlClass() and - what = def.getVariable().getName() + " at " + def.getLocation() and - problem = "has non-disjoint subclasses" | - strictcount(def.getAQlClass()) > 2 or + what = def.getVariable().getName() + " at " + def.getLocation() and + problem = "has non-disjoint subclasses" + | + strictcount(def.getAQlClass()) > 2 + or /* OK if method call and argument overlap: `x.foo(x)` */ strictcount(def.getAQlClass()) > 1 and - not clsname = "ArgumentRefinement" and not clsname = "SelfCallsiteRefinement" + not clsname = "ArgumentRefinement" and + not clsname = "SelfCallsiteRefinement" ) or exists(EssaDefinition def | clsname = def.getAQlClass() and clsname.prefix(4) = "Essa" and - what = " at " + def.getLocation() and + what = " at " + def.getLocation() and problem = "not covered by Python-specific subclass." ) or // All modules should have __name__ exists(Module m | - what = " at " + m.getLocation() and - clsname = "Module" | + what = " at " + m.getLocation() and + clsname = "Module" + | not exists(m.getName()) and problem = "does not have a name" or @@ -113,7 +134,8 @@ predicate undefined_sanity(string clsname, string problem, string what) { /* Variables may be undefined, but values cannot be */ exists(ControlFlowNode f | PointsToInternal::pointsTo(f, _, ObjectInternal::undefined(), _) and - clsname = f.getAQlClass() and not clsname = "AnyNode" and + clsname = f.getAQlClass() and + not clsname = "AnyNode" and problem = " points-to an undefined variable" and what = f.toString() ) @@ -122,4 +144,3 @@ predicate undefined_sanity(string clsname, string problem, string what) { from string clsname, string problem, string what where ssa_sanity(clsname, problem, what) or undefined_sanity(clsname, problem, what) select clsname, what, problem - diff --git a/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql b/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql index 08928b0c9f0..8cf0b4c15a6 100644 --- a/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql @@ -1,7 +1,5 @@ - import python import semmle.python.pointsto.PointsTo - import Util from SsaSourceVariable var, ControlFlowNode use, BasicBlock pred diff --git a/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql b/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql index 53e5d69953e..a1547da65c6 100644 --- a/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql @@ -1,14 +1,13 @@ - import python import semmle.python.pointsto.PointsTo - import Util from SsaSourceVariable var, ControlFlowNode defn, string kind -where not var instanceof SpecialSsaSourceVariable and -( - var.hasDefiningNode(defn) and kind = "definition" - or - var.hasRefinement(_, defn) and kind = "refinement" -) +where + not var instanceof SpecialSsaSourceVariable and + ( + var.hasDefiningNode(defn) and kind = "definition" + or + var.hasRefinement(_, defn) and kind = "refinement" + ) select locate(defn.getLocation(), "ab"), var.(Variable), defn.toString(), kind diff --git a/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql b/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql index 4a4d83160c3..dc71ac5df65 100644 --- a/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql +++ b/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql @@ -1,12 +1,11 @@ - import python private import semmle.python.pointsto.PointsTo private import semmle.python.objects.ObjectInternal import Util from EssaVariable var, string name, ObjectInternal o, Context ctx -where AttributePointsTo::variableAttributePointsTo(var, ctx, name, o, _) and not var.getSourceVariable() instanceof SpecialSsaSourceVariable -select -locate(var.getDefinition().getLocation(), "abdfgikm"), var.getRepresentation(), -name, var.getDefinition().getRepresentation(), o, ctx - +where + AttributePointsTo::variableAttributePointsTo(var, ctx, name, o, _) and + not var.getSourceVariable() instanceof SpecialSsaSourceVariable +select locate(var.getDefinition().getLocation(), "abdfgikm"), var.getRepresentation(), name, + var.getDefinition().getRepresentation(), o, ctx diff --git a/python/ql/test/library-tests/PointsTo/new/SsaUses.ql b/python/ql/test/library-tests/PointsTo/new/SsaUses.ql index 9c01da90a59..2a8e8f1e750 100644 --- a/python/ql/test/library-tests/PointsTo/new/SsaUses.ql +++ b/python/ql/test/library-tests/PointsTo/new/SsaUses.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import Util diff --git a/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql b/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql index 0a17a3e118a..2367df63b63 100644 --- a/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql +++ b/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql @@ -1,19 +1,19 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext import Util - -from ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx, ControlFlowNode origin, string what -where -not use instanceof NameConstantNode and -not use.getNode() instanceof ImmutableLiteral and -eval = Conditionals::testEvaluates(test, use, ctx, val, origin) and -( - what = val.getSource().(Object).toString() - or - not exists(val.getSource()) and what = origin.getNode().toString() -) -select locate(test.getLocation(), "bc"), test.getNode().toString(), eval.toString(), use.getNode().toString(), what - +from + ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx, + ControlFlowNode origin, string what +where + not use instanceof NameConstantNode and + not use.getNode() instanceof ImmutableLiteral and + eval = Conditionals::testEvaluates(test, use, ctx, val, origin) and + ( + what = val.getSource().(Object).toString() + or + not exists(val.getSource()) and what = origin.getNode().toString() + ) +select locate(test.getLocation(), "bc"), test.getNode().toString(), eval.toString(), + use.getNode().toString(), what diff --git a/python/ql/test/library-tests/PointsTo/new/Values.ql b/python/ql/test/library-tests/PointsTo/new/Values.ql index 8e6bd9c9f00..754fcfede54 100644 --- a/python/ql/test/library-tests/PointsTo/new/Values.ql +++ b/python/ql/test/library-tests/PointsTo/new/Values.ql @@ -1,9 +1,7 @@ - import python import Util - from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin -where - f.pointsTo(ctx, v, origin) -select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), ctx, vrepr(v), vrepr(v.getClass()) +where f.pointsTo(ctx, v, origin) +select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), ctx, vrepr(v), + vrepr(v.getClass()) diff --git a/python/ql/test/library-tests/PointsTo/new/VarUses.ql b/python/ql/test/library-tests/PointsTo/new/VarUses.ql index a8ef096821e..56c1ca637a1 100644 --- a/python/ql/test/library-tests/PointsTo/new/VarUses.ql +++ b/python/ql/test/library-tests/PointsTo/new/VarUses.ql @@ -1,8 +1,9 @@ - import python import semmle.python.pointsto.PointsTo import Util from SsaSourceVariable var, ControlFlowNode use -where (use = var.getAUse() or var.hasRefinement(use, _)) and not var instanceof SpecialSsaSourceVariable +where + (use = var.getAUse() or var.hasRefinement(use, _)) and + not var instanceof SpecialSsaSourceVariable select locate(use.getLocation(), "abd"), var.getName(), use.toString() diff --git a/python/ql/test/library-tests/PointsTo/properties/Lookup.ql b/python/ql/test/library-tests/PointsTo/properties/Lookup.ql index 10c32412d85..d7820250723 100644 --- a/python/ql/test/library-tests/PointsTo/properties/Lookup.ql +++ b/python/ql/test/library-tests/PointsTo/properties/Lookup.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal diff --git a/python/ql/test/library-tests/PointsTo/properties/Values.ql b/python/ql/test/library-tests/PointsTo/properties/Values.ql index 0173d7d6219..597a54cb641 100644 --- a/python/ql/test/library-tests/PointsTo/properties/Values.ql +++ b/python/ql/test/library-tests/PointsTo/properties/Values.ql @@ -1,4 +1,3 @@ - import python import semmle.python.objects.ObjectInternal @@ -10,6 +9,5 @@ string vrepr(Value v) { } from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin -where - f.pointsTo(ctx, v, origin) +where f.pointsTo(ctx, v, origin) select f.getLocation(), f.toString(), ctx, vrepr(v), vrepr(v.getClass()) diff --git a/python/ql/test/library-tests/PointsTo/returns/Test.ql b/python/ql/test/library-tests/PointsTo/returns/Test.ql index a30d0ef1c76..8546de90f24 100644 --- a/python/ql/test/library-tests/PointsTo/returns/Test.ql +++ b/python/ql/test/library-tests/PointsTo/returns/Test.ql @@ -1,4 +1,4 @@ import python from PyFunctionObject f -select f.toString(), f.getAnInferredReturnType().toString() \ No newline at end of file +select f.toString(), f.getAnInferredReturnType().toString() diff --git a/python/ql/test/library-tests/PointsTo/subclass/Checks.ql b/python/ql/test/library-tests/PointsTo/subclass/Checks.ql index b164406276e..a82002b1d5f 100644 --- a/python/ql/test/library-tests/PointsTo/subclass/Checks.ql +++ b/python/ql/test/library-tests/PointsTo/subclass/Checks.ql @@ -1,7 +1,6 @@ - import python import semmle.python.pointsto.PointsTo -from Value sup, Value cls +from Value sup, Value cls where Expressions::requireSubClass(cls, sup) select cls, sup diff --git a/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql b/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql index fd32bfcbe64..0f197edeb0a 100644 --- a/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql +++ b/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql @@ -1,12 +1,12 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal import semmle.python.pointsto.PointsToContext - -from ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx +from + ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx where -PointsTo::pointsTo(use, ctx, val, _) and -eval = Conditionals::testEvaluates(test, use, ctx, val, _) -select test.getLocation().getStartLine(), test.getNode().toString(), eval.toString(), use.getNode().toString(), val.toString() + PointsTo::pointsTo(use, ctx, val, _) and + eval = Conditionals::testEvaluates(test, use, ctx, val, _) +select test.getLocation().getStartLine(), test.getNode().toString(), eval.toString(), + use.getNode().toString(), val.toString() diff --git a/python/ql/test/library-tests/PointsTo/subclass/Values.ql b/python/ql/test/library-tests/PointsTo/subclass/Values.ql index 3246ef02764..c50e25c5f36 100644 --- a/python/ql/test/library-tests/PointsTo/subclass/Values.ql +++ b/python/ql/test/library-tests/PointsTo/subclass/Values.ql @@ -1,10 +1,7 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from ControlFlowNode f, ObjectInternal v, ControlFlowNode x - where PointsTo::pointsTo(f, _, v, x) - select f.getLocation().getStartLine(), f.toString(), v, x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql b/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql index f21b102338f..6245b56f711 100644 --- a/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql +++ b/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql @@ -1,10 +1,11 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext import semmle.python.objects.ObjectInternal from CallNode call, SuperInstance sup, BoundMethodObjectInternal bm -where call.getFunction().inferredValue() = bm and -call.getFunction().(AttrNode).getObject().inferredValue() = sup -select call.getLocation().getStartLine(), call.toString(), bm.getFunction().getSource().(FunctionObject).getQualifiedName() \ No newline at end of file +where + call.getFunction().inferredValue() = bm and + call.getFunction().(AttrNode).getObject().inferredValue() = sup +select call.getLocation().getStartLine(), call.toString(), + bm.getFunction().getSource().(FunctionObject).getQualifiedName() diff --git a/python/ql/test/library-tests/attributes/SelfAttribute.ql b/python/ql/test/library-tests/attributes/SelfAttribute.ql index 0ccfe5a397c..7ac995d2061 100644 --- a/python/ql/test/library-tests/attributes/SelfAttribute.ql +++ b/python/ql/test/library-tests/attributes/SelfAttribute.ql @@ -1,11 +1,9 @@ - import python import semmle.python.SelfAttribute from SelfAttributeRead sa, int line, string g, string l where -line = sa.getLocation().getStartLine() and -if sa.guardedByHasattr() then g = "guarded" else g = "" and - -if sa.locallyDefined() then l = "defined" else l = "" + line = sa.getLocation().getStartLine() and + (if sa.guardedByHasattr() then g = "guarded" else g = "") and + if sa.locallyDefined() then l = "defined" else l = "" select line, sa.getName(), g + l diff --git a/python/ql/test/library-tests/classes/abstract/Abstract.ql b/python/ql/test/library-tests/classes/abstract/Abstract.ql index 1117bc95790..6773bb22785 100644 --- a/python/ql/test/library-tests/classes/abstract/Abstract.ql +++ b/python/ql/test/library-tests/classes/abstract/Abstract.ql @@ -1,12 +1,7 @@ - import python from ClassObject cls, string abstract where -not cls.isBuiltin() and -if cls.isAbstract() then - abstract = "yes" -else - abstract = "no" - + not cls.isBuiltin() and + if cls.isAbstract() then abstract = "yes" else abstract = "no" select cls.toString(), abstract diff --git a/python/ql/test/library-tests/classes/attr/class_attr.ql b/python/ql/test/library-tests/classes/attr/class_attr.ql index 0b283debd5d..3b7bf8b3ba0 100644 --- a/python/ql/test/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") -select line, cls.toString(), name, obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") +select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/library-tests/classes/attr/class_defined_attr.ql b/python/ql/test/library-tests/classes/attr/class_defined_attr.ql index 843b1ed2b3a..ec798dcf190 100644 --- a/python/ql/test/library-tests/classes/attr/class_defined_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_defined_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.declaredAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.declaredAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/library-tests/classes/attr/class_defines_attr.ql b/python/ql/test/library-tests/classes/attr/class_defines_attr.ql index e9cfdee5ccd..858d3e49e20 100644 --- a/python/ql/test/library-tests/classes/attr/class_defines_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_defines_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.declaresAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.declaresAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/library-tests/classes/attr/class_has_attr.ql index a274a1dd95b..2f16aa4ca97 100644 --- a/python/ql/test/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_has_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.hasAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.hasAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/library-tests/classes/attr/hash.ql b/python/ql/test/library-tests/classes/attr/hash.ql index b4485634cce..a8ccf6c9d6b 100644 --- a/python/ql/test/library-tests/classes/attr/hash.ql +++ b/python/ql/test/library-tests/classes/attr/hash.ql @@ -7,9 +7,10 @@ import python from ClassObject cls, int line, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute("__hash__") and -not cls.isC() and -not obj = theObjectType().lookupAttribute("__hash__") and -not obj = theTypeType().lookupAttribute("__hash__") -select line, cls.toString(), obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute("__hash__") and + not cls.isC() and + not obj = theObjectType().lookupAttribute("__hash__") and + not obj = theTypeType().lookupAttribute("__hash__") +select line, cls.toString(), obj.toString() diff --git a/python/ql/test/library-tests/classes/mro/C3.ql b/python/ql/test/library-tests/classes/mro/C3.ql index e433971f1eb..981a55893c2 100644 --- a/python/ql/test/library-tests/classes/mro/C3.ql +++ b/python/ql/test/library-tests/classes/mro/C3.ql @@ -1,9 +1,6 @@ - import python import semmle.python.pointsto.MRO from ClassValue cls where not cls.isBuiltin() - select cls.toString(), Mro::newStyleMro(cls) - diff --git a/python/ql/test/library-tests/comments/blocks.ql b/python/ql/test/library-tests/comments/blocks.ql index 3fbb6946c02..ac306cb3f44 100644 --- a/python/ql/test/library-tests/comments/blocks.ql +++ b/python/ql/test/library-tests/comments/blocks.ql @@ -10,4 +10,4 @@ import Lexical.CommentedOutCode from CommentedOutCodeBlock c, int bl, int el where c.hasLocationInfo(_, bl, _, el, _) -select bl, el, c.toString() \ No newline at end of file +select bl, el, c.toString() diff --git a/python/ql/test/library-tests/comments/blocks_not_example.ql b/python/ql/test/library-tests/comments/blocks_not_example.ql index ccc8c0ba50b..19ed6283a3e 100644 --- a/python/ql/test/library-tests/comments/blocks_not_example.ql +++ b/python/ql/test/library-tests/comments/blocks_not_example.ql @@ -1,7 +1,6 @@ - import python import Lexical.CommentedOutCode from CommentedOutCodeBlock c, int bl, int el where c.hasLocationInfo(_, bl, _, el, _) and not c.maybeExampleCode() -select bl, el, c.toString() \ No newline at end of file +select bl, el, c.toString() diff --git a/python/ql/test/library-tests/comments/length.ql b/python/ql/test/library-tests/comments/length.ql index 53d514e6b33..0a15328c35e 100644 --- a/python/ql/test/library-tests/comments/length.ql +++ b/python/ql/test/library-tests/comments/length.ql @@ -1,8 +1,8 @@ - import python import Lexical.CommentedOutCode from CommentBlock block, int line, boolean code -where block.hasLocationInfo(_, line, _, _, _) and -if block instanceof CommentedOutCodeBlock then code = true else code = false +where + block.hasLocationInfo(_, line, _, _, _) and + if block instanceof CommentedOutCodeBlock then code = true else code = false select line, block.length(), code diff --git a/python/ql/test/library-tests/comments/lines.ql b/python/ql/test/library-tests/comments/lines.ql index a07d2ac1953..d71eb039129 100644 --- a/python/ql/test/library-tests/comments/lines.ql +++ b/python/ql/test/library-tests/comments/lines.ql @@ -1,7 +1,6 @@ - import python import Lexical.CommentedOutCode from CommentedOutCodeLine c, int l where l = c.getLocation().getStartLine() -select l, c.toString() \ No newline at end of file +select l, c.toString() diff --git a/python/ql/test/library-tests/comments/lines_not_example.ql b/python/ql/test/library-tests/comments/lines_not_example.ql index e6fcaab9d93..2fa0dec3a4e 100644 --- a/python/ql/test/library-tests/comments/lines_not_example.ql +++ b/python/ql/test/library-tests/comments/lines_not_example.ql @@ -1,7 +1,6 @@ - import python import Lexical.CommentedOutCode from CommentedOutCodeLine c, int l where l = c.getLocation().getStartLine() and not c.maybeExampleCode() -select l, c.toString() \ No newline at end of file +select l, c.toString() diff --git a/python/ql/test/library-tests/comments/type_hint.ql b/python/ql/test/library-tests/comments/type_hint.ql index 55ec57c0d5b..26511a2d97f 100644 --- a/python/ql/test/library-tests/comments/type_hint.ql +++ b/python/ql/test/library-tests/comments/type_hint.ql @@ -1,6 +1,4 @@ - import python from TypeHintComment c select c.getLocation().toString(), c.getText() - diff --git a/python/ql/test/library-tests/comparisons/Compare.ql b/python/ql/test/library-tests/comparisons/Compare.ql index 84d97bbbbe2..558da6fc6d7 100644 --- a/python/ql/test/library-tests/comparisons/Compare.ql +++ b/python/ql/test/library-tests/comparisons/Compare.ql @@ -1,9 +1,6 @@ - import python - import semmle.python.Comparisons from Comparison c, ControlFlowNode l, CompareOp op, float k -where -c.tests(l, op, k) +where c.tests(l, op, k) select c.getLocation().getStartLine(), l + " " + op.repr() + " " + k diff --git a/python/ql/test/library-tests/comparisons/Compare2.ql b/python/ql/test/library-tests/comparisons/Compare2.ql index 70d954a4b0e..ade279c9efd 100644 --- a/python/ql/test/library-tests/comparisons/Compare2.ql +++ b/python/ql/test/library-tests/comparisons/Compare2.ql @@ -1,11 +1,12 @@ - import python - import semmle.python.Comparisons from Comparison c, NameNode l, CompareOp op, NameNode r, float k, string add -where -c.tests(l, op, r, k) -and -(k < 0 and add = "" or k >= 0 and add = "+") +where + c.tests(l, op, r, k) and + ( + k < 0 and add = "" + or + k >= 0 and add = "+" + ) select c.getLocation().getStartLine(), l.getId() + " " + op.repr() + " " + r.getId() + add + k diff --git a/python/ql/test/library-tests/comparisons/CompareControls.ql b/python/ql/test/library-tests/comparisons/CompareControls.ql index 01b35c0ffad..b803e40dfed 100644 --- a/python/ql/test/library-tests/comparisons/CompareControls.ql +++ b/python/ql/test/library-tests/comparisons/CompareControls.ql @@ -1,10 +1,7 @@ - import python - import semmle.python.Comparisons from ComparisonControlBlock comp, SsaVariable v, CompareOp op, float k, BasicBlock b -where -comp.controls(v.getAUse(), op, k, b) - -select comp.getTest().getLocation().getStartLine(), v.getId() + " " + op.repr() + " " + k, b.getNode(0).getLocation().getStartLine() +where comp.controls(v.getAUse(), op, k, b) +select comp.getTest().getLocation().getStartLine(), v.getId() + " " + op.repr() + " " + k, + b.getNode(0).getLocation().getStartLine() diff --git a/python/ql/test/library-tests/comparisons/Implication.ql b/python/ql/test/library-tests/comparisons/Implication.ql index f24d1d42234..f94d8ba184a 100644 --- a/python/ql/test/library-tests/comparisons/Implication.ql +++ b/python/ql/test/library-tests/comparisons/Implication.ql @@ -1,9 +1,6 @@ - import python import semmle.python.Comparisons from Comparison a, Comparison that, boolean thisIsTrue, boolean thatIsTrue - where a.impliesThat(thisIsTrue, that, thatIsTrue) - -select a.getLocation().getStartLine(), thisIsTrue, that.getLocation().getStartLine(), thatIsTrue \ No newline at end of file +select a.getLocation().getStartLine(), thisIsTrue, that.getLocation().getStartLine(), thatIsTrue diff --git a/python/ql/test/library-tests/comprehensions/Flow.ql b/python/ql/test/library-tests/comprehensions/Flow.ql index e19d4d75abe..5fd3a0cc61c 100644 --- a/python/ql/test/library-tests/comprehensions/Flow.ql +++ b/python/ql/test/library-tests/comprehensions/Flow.ql @@ -2,4 +2,4 @@ import python from ControlFlowNode p, ControlFlowNode s where p.getASuccessor() = s -select p.getLocation().getStartLine(), p.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +select p.getLocation().getStartLine(), p.toString(), s.getLocation().getStartLine(), s.toString() diff --git a/python/ql/test/library-tests/dependencies/Dependencies.ql b/python/ql/test/library-tests/dependencies/Dependencies.ql index b5bedbe7b3c..cab84c4417b 100644 --- a/python/ql/test/library-tests/dependencies/Dependencies.ql +++ b/python/ql/test/library-tests/dependencies/Dependencies.ql @@ -1,8 +1,7 @@ - import python import semmle.python.dependencies.Dependencies from DependencyKind dk, AstNode src, Object target where dk.isADependency(src, target) -select dk.toString(), src.getLocation().getFile().getShortName(), src.getLocation().getStartLine(), src.toString(), target.toString() - +select dk.toString(), src.getLocation().getFile().getShortName(), src.getLocation().getStartLine(), + src.toString(), target.toString() diff --git a/python/ql/test/library-tests/descriptors/Descriptors.ql b/python/ql/test/library-tests/descriptors/Descriptors.ql index 658091bfe4e..dd97b623f7f 100644 --- a/python/ql/test/library-tests/descriptors/Descriptors.ql +++ b/python/ql/test/library-tests/descriptors/Descriptors.ql @@ -1,13 +1,9 @@ - import python from ClassObject cls, string kind -where cls.isDescriptorType() and -/* Exclude bound-method as its name differs between 2 and 3 */ -not cls = theBoundMethodType() and -(if cls.isOverridingDescriptorType() then - kind = "overriding" - else - kind = "non-overriding" -) -select cls.toString(), kind \ No newline at end of file +where + cls.isDescriptorType() and + /* Exclude bound-method as its name differs between 2 and 3 */ + not cls = theBoundMethodType() and + (if cls.isOverridingDescriptorType() then kind = "overriding" else kind = "non-overriding") +select cls.toString(), kind diff --git a/python/ql/test/library-tests/descriptors/Methods.ql b/python/ql/test/library-tests/descriptors/Methods.ql index 75d3092198d..4a2ec39d70c 100644 --- a/python/ql/test/library-tests/descriptors/Methods.ql +++ b/python/ql/test/library-tests/descriptors/Methods.ql @@ -1,15 +1,11 @@ - import python import semmle.python.types.Descriptors -int lineof(Object o) { - result = o.getOrigin().getLocation().getStartLine() -} +int lineof(Object o) { result = o.getOrigin().getLocation().getStartLine() } from Object m, FunctionObject f -where - m.(ClassMethodObject).getFunction() = f - or - m.(StaticMethodObject).getFunction() = f +where + m.(ClassMethodObject).getFunction() = f + or + m.(StaticMethodObject).getFunction() = f select lineof(m), m.toString(), lineof(f), f.toString() - diff --git a/python/ql/test/library-tests/encoding/CheckEncoding.ql b/python/ql/test/library-tests/encoding/CheckEncoding.ql index 88e8a580027..60fc167e293 100644 --- a/python/ql/test/library-tests/encoding/CheckEncoding.ql +++ b/python/ql/test/library-tests/encoding/CheckEncoding.ql @@ -2,7 +2,7 @@ import python from File f, string encoding where -encoding = f.getSpecifiedEncoding() -or -not exists(f.getSpecifiedEncoding()) and encoding = "none" + encoding = f.getSpecifiedEncoding() + or + not exists(f.getSpecifiedEncoding()) and encoding = "none" select f.getAbsolutePath(), encoding diff --git a/python/ql/test/library-tests/exceptions/Handles.ql b/python/ql/test/library-tests/exceptions/Handles.ql index 989126b7127..620944de5b9 100644 --- a/python/ql/test/library-tests/exceptions/Handles.ql +++ b/python/ql/test/library-tests/exceptions/Handles.ql @@ -2,4 +2,4 @@ import python from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) -select ex.getLocation().getStartLine(), ex.toString(), val.toString() \ No newline at end of file +select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/library-tests/exceptions/Legal.ql b/python/ql/test/library-tests/exceptions/Legal.ql index 37488eb082b..eb27a82d614 100644 --- a/python/ql/test/library-tests/exceptions/Legal.ql +++ b/python/ql/test/library-tests/exceptions/Legal.ql @@ -2,10 +2,9 @@ import python from ClassObject cls, string legal where -not cls.isC() and cls.isLegalExceptionType() and legal = "yes" and not cls.failedInference() -or -not cls.isC() and not cls.isLegalExceptionType() and legal = "no" and not cls.failedInference() -or -not cls.isC() and cls.failedInference(legal) - + not cls.isC() and cls.isLegalExceptionType() and legal = "yes" and not cls.failedInference() + or + not cls.isC() and not cls.isLegalExceptionType() and legal = "no" and not cls.failedInference() + or + not cls.isC() and cls.failedInference(legal) select cls.toString(), legal diff --git a/python/ql/test/library-tests/exprs/ast/AstParent.ql b/python/ql/test/library-tests/exprs/ast/AstParent.ql index 3e26f672360..f472a6f6e5b 100644 --- a/python/ql/test/library-tests/exprs/ast/AstParent.ql +++ b/python/ql/test/library-tests/exprs/ast/AstParent.ql @@ -1,6 +1,4 @@ import python -select -count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) -+ -count(AstNode c | strictcount(c.getParentNode()) > 1) \ No newline at end of file +select count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) + + count(AstNode c | strictcount(c.getParentNode()) > 1) diff --git a/python/ql/test/library-tests/exprs/ast/Child.ql b/python/ql/test/library-tests/exprs/ast/Child.ql index 0638f6c4e22..5b363a6ddb2 100644 --- a/python/ql/test/library-tests/exprs/ast/Child.ql +++ b/python/ql/test/library-tests/exprs/ast/Child.ql @@ -3,4 +3,3 @@ import python from AstNode p, AstNode c where p.getAChildNode() = c select p.getLocation().getStartLine(), p.toString(), c.getLocation().getStartLine(), c - diff --git a/python/ql/test/library-tests/exprs/compare/Test.ql b/python/ql/test/library-tests/exprs/compare/Test.ql index 7aa2102f8b8..80feac5185a 100644 --- a/python/ql/test/library-tests/exprs/compare/Test.ql +++ b/python/ql/test/library-tests/exprs/compare/Test.ql @@ -1,8 +1,6 @@ - import python import semmle.python.TestUtils - from Compare comp, Expr left, Expr right, Cmpop op where comp.compares(left, op, right) select compact_location(comp), comp.toString(), left.toString(), op.toString(), right.toString() diff --git a/python/ql/test/library-tests/exprs/strings/Strings.ql b/python/ql/test/library-tests/exprs/strings/Strings.ql index e3a757c4725..7d6a697a8ed 100644 --- a/python/ql/test/library-tests/exprs/strings/Strings.ql +++ b/python/ql/test/library-tests/exprs/strings/Strings.ql @@ -1,4 +1,3 @@ - import python from StrConst s diff --git a/python/ql/test/library-tests/filters/generated/Filter.ql b/python/ql/test/library-tests/filters/generated/Filter.ql index 39c0e2b2344..389440ffd3a 100644 --- a/python/ql/test/library-tests/filters/generated/Filter.ql +++ b/python/ql/test/library-tests/filters/generated/Filter.ql @@ -1,4 +1,3 @@ - import python import semmle.python.filters.GeneratedCode diff --git a/python/ql/test/library-tests/filters/tests/Filter.ql b/python/ql/test/library-tests/filters/tests/Filter.ql index e20231ea5fa..71d6d2c668d 100644 --- a/python/ql/test/library-tests/filters/tests/Filter.ql +++ b/python/ql/test/library-tests/filters/tests/Filter.ql @@ -1,4 +1,3 @@ - import python import semmle.python.filters.Tests diff --git a/python/ql/test/library-tests/formatting/FormatArguments.ql b/python/ql/test/library-tests/formatting/FormatArguments.ql index 19e47b7fc44..f2cc38f7e8c 100644 --- a/python/ql/test/library-tests/formatting/FormatArguments.ql +++ b/python/ql/test/library-tests/formatting/FormatArguments.ql @@ -1,10 +1,9 @@ - import python import Expressions.Formatting.AdvancedFormatting from AdvancedFormatString a, string name, int start, int end -where -name = "'" + a.getFieldName(start, end) + "'" -or -name = a.getFieldNumber(start, end).toString() +where + name = "'" + a.getFieldName(start, end) + "'" + or + name = a.getFieldNumber(start, end).toString() select a.getLocation().getStartLine(), a.getText(), start, end, name diff --git a/python/ql/test/library-tests/formatting/FormatFields.ql b/python/ql/test/library-tests/formatting/FormatFields.ql index b8a3b913355..f629a779082 100644 --- a/python/ql/test/library-tests/formatting/FormatFields.ql +++ b/python/ql/test/library-tests/formatting/FormatFields.ql @@ -1,4 +1,3 @@ - import python import Expressions.Formatting.AdvancedFormatting diff --git a/python/ql/test/library-tests/imports/Alias.ql b/python/ql/test/library-tests/imports/Alias.ql index 5a7c034d02a..a08d1c6543b 100644 --- a/python/ql/test/library-tests/imports/Alias.ql +++ b/python/ql/test/library-tests/imports/Alias.ql @@ -2,4 +2,4 @@ import python from Alias a, ImportMember i where i = a.getValue() -select a.toString(), i.getName(), a.getAsname().toString() \ No newline at end of file +select a.toString(), i.getName(), a.getAsname().toString() diff --git a/python/ql/test/library-tests/jump_to_defn/Remote.ql b/python/ql/test/library-tests/jump_to_defn/Remote.ql index 18b0ebacdc0..7602e5839d3 100644 --- a/python/ql/test/library-tests/jump_to_defn/Remote.ql +++ b/python/ql/test/library-tests/jump_to_defn/Remote.ql @@ -1,10 +1,10 @@ - import python import analysis.DefinitionTracking import analysis.CrossProjectDefinitions from Definition defn, Symbol s -where s.find() = defn.getAstNode() and -// Exclude dunder names as these vary from version to version. -not s.toString().regexpMatch(".+__") +where + s.find() = defn.getAstNode() and + // Exclude dunder names as these vary from version to version. + not s.toString().regexpMatch(".+__") select s.toString() diff --git a/python/ql/test/library-tests/jump_to_defn/Sanity.ql b/python/ql/test/library-tests/jump_to_defn/Sanity.ql index 0e4455ab09b..ba274e0aa21 100644 --- a/python/ql/test/library-tests/jump_to_defn/Sanity.ql +++ b/python/ql/test/library-tests/jump_to_defn/Sanity.ql @@ -1,4 +1,3 @@ - import python import analysis.DefinitionTracking import analysis.CrossProjectDefinitions @@ -6,11 +5,11 @@ import analysis.CrossProjectDefinitions predicate local_problem(Definition defn, string issue, string repr) { not exists(defn.toString()) and issue = "no toString()" and repr = "a local definition" or - not exists(defn.getAstNode()) and issue = "no getAstNode()" and repr = defn.toString() + not exists(defn.getAstNode()) and issue = "no getAstNode()" and repr = defn.toString() or - not exists(defn.getLocation()) and issue = "no getLocation()" and repr = defn.toString() + not exists(defn.getLocation()) and issue = "no getLocation()" and repr = defn.toString() or - count(defn.getLocation())> 1 and issue = "more than one getLocation()" and repr = defn.toString() + count(defn.getLocation()) > 1 and issue = "more than one getLocation()" and repr = defn.toString() } predicate remote_problem(Symbol s, string issue, string repr) { diff --git a/python/ql/test/library-tests/jump_to_defn/Symbol.ql b/python/ql/test/library-tests/jump_to_defn/Symbol.ql index 7f111863b06..446f6b47b51 100644 --- a/python/ql/test/library-tests/jump_to_defn/Symbol.ql +++ b/python/ql/test/library-tests/jump_to_defn/Symbol.ql @@ -1,8 +1,5 @@ - import python import analysis.CrossProjectDefinitions from Symbol symbol - select symbol.toString(), symbol.find().getLocation().toString() - diff --git a/python/ql/test/library-tests/jump_to_defn/test.ql b/python/ql/test/library-tests/jump_to_defn/test.ql index ed8bf8ab84c..0f952578997 100644 --- a/python/ql/test/library-tests/jump_to_defn/test.ql +++ b/python/ql/test/library-tests/jump_to_defn/test.ql @@ -6,6 +6,7 @@ import python import analysis.DefinitionTracking from Expr use, Definition defn -where defn = getADefinition(use) -and use.getEnclosingModule().getName() = "test" +where + defn = getADefinition(use) and + use.getEnclosingModule().getName() = "test" select use.getLocation().toString(), use.toString(), defn.toString() diff --git a/python/ql/test/library-tests/locations/elif/test.ql b/python/ql/test/library-tests/locations/elif/test.ql index ca7177e847c..b2e7f4b164d 100644 --- a/python/ql/test/library-tests/locations/elif/test.ql +++ b/python/ql/test/library-tests/locations/elif/test.ql @@ -2,4 +2,4 @@ import python from AstNode ast, Location l where ast.getLocation() = l -select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql b/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql index 2687a785f1b..aac64976f75 100644 --- a/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql +++ b/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql @@ -1,12 +1,9 @@ import python class ImplicitConcat extends StrConst { - ImplicitConcat() { - exists(this.getAnImplicitlyConcatenatedPart()) - } + ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) } } - + from StringPart s - - -select s.getLocation().getStartLine(), s.getText(), s.getLocation().getStartColumn(), s.getLocation().getEndColumn() \ No newline at end of file +select s.getLocation().getStartLine(), s.getText(), s.getLocation().getStartColumn(), + s.getLocation().getEndColumn() diff --git a/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql b/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql index 1b1a0d492b3..49fe354b6ee 100644 --- a/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql +++ b/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql @@ -1,14 +1,9 @@ import python class ImplicitConcat extends StrConst { - ImplicitConcat() { - exists(this.getAnImplicitlyConcatenatedPart()) - } + ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) } } - + from StrConst s, StringPart part, int n -where - part = s.getImplicitlyConcatenatedPart(n) - - -select s.getLocation().getStartLine(), s.getText(), n, part.getText() \ No newline at end of file +where part = s.getImplicitlyConcatenatedPart(n) +select s.getLocation().getStartLine(), s.getText(), n, part.getText() diff --git a/python/ql/test/library-tests/locations/implicit_concatenation/test.ql b/python/ql/test/library-tests/locations/implicit_concatenation/test.ql index 5b2f6ae0a55..09ba3dcd1c4 100644 --- a/python/ql/test/library-tests/locations/implicit_concatenation/test.ql +++ b/python/ql/test/library-tests/locations/implicit_concatenation/test.ql @@ -1,16 +1,13 @@ import python class ImplicitConcat extends StrConst { - ImplicitConcat() { - exists(this.getAnImplicitlyConcatenatedPart()) - } + ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) } } - + from StrConst s, boolean isConcat -where - s instanceof ImplicitConcat and isConcat = true - or - not s instanceof ImplicitConcat and isConcat = false - - -select s.getLocation().getStartLine(), s.getText(), isConcat, s.getText().length(), s.getLocation().getStartColumn(), s.getLocation().getEndColumn() \ No newline at end of file +where + s instanceof ImplicitConcat and isConcat = true + or + not s instanceof ImplicitConcat and isConcat = false +select s.getLocation().getStartLine(), s.getText(), isConcat, s.getText().length(), + s.getLocation().getStartColumn(), s.getLocation().getEndColumn() diff --git a/python/ql/test/library-tests/locations/negative_numbers/negative.ql b/python/ql/test/library-tests/locations/negative_numbers/negative.ql index c423cb0532c..0fe2cdcc2bc 100644 --- a/python/ql/test/library-tests/locations/negative_numbers/negative.ql +++ b/python/ql/test/library-tests/locations/negative_numbers/negative.ql @@ -1,13 +1,7 @@ import python -from Expr e, int bl, int bc, int el,int ec, string p - -where - e.getLocation().hasLocationInfo(_, bl, bc, el, ec) - and - if e.isParenthesized() then - p = "()" - else - p = "" - -select e.toString(), bl, bc, el, ec, p \ No newline at end of file +from Expr e, int bl, int bc, int el, int ec, string p +where + e.getLocation().hasLocationInfo(_, bl, bc, el, ec) and + if e.isParenthesized() then p = "()" else p = "" +select e.toString(), bl, bc, el, ec, p diff --git a/python/ql/test/library-tests/locations/nested_classes/Test.ql b/python/ql/test/library-tests/locations/nested_classes/Test.ql index 693d6f7116f..143df5fee6f 100644 --- a/python/ql/test/library-tests/locations/nested_classes/Test.ql +++ b/python/ql/test/library-tests/locations/nested_classes/Test.ql @@ -1,7 +1,5 @@ - import python from Class cls, Location l where l = cls.getLocation() - select cls.getName(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/library-tests/modules/duplicate_name/Modules.ql b/python/ql/test/library-tests/modules/duplicate_name/Modules.ql index 536689d0f90..a6477c7d6af 100644 --- a/python/ql/test/library-tests/modules/duplicate_name/Modules.ql +++ b/python/ql/test/library-tests/modules/duplicate_name/Modules.ql @@ -1,7 +1,5 @@ - import python from string name, int mcnt where mcnt = strictcount(Module m | m.getName() = name) and mcnt > 1 select name, mcnt, strictcount(ModuleValue val | val.getName() = name) - diff --git a/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql b/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql index a3a54953513..bc7bc0526ec 100644 --- a/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql +++ b/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql @@ -1,4 +1,3 @@ - import python from Module m diff --git a/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql b/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql index a3a54953513..bc7bc0526ec 100644 --- a/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql +++ b/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql @@ -1,4 +1,3 @@ - import python from Module m diff --git a/python/ql/test/library-tests/objects/Literals.ql b/python/ql/test/library-tests/objects/Literals.ql index f83f4e722da..ad6e1181cfd 100644 --- a/python/ql/test/library-tests/objects/Literals.ql +++ b/python/ql/test/library-tests/objects/Literals.ql @@ -1,8 +1,6 @@ - /* Test that there are no literals that do not have a corresponding object. */ import python - string repr(Expr e) { result = e.(Num).getN() or result = e.(Bytes).getS() or @@ -10,7 +8,5 @@ string repr(Expr e) { } from ImmutableLiteral l -where -not exists(l.getLiteralObject()) - -select l.getLocation().getStartLine(), repr(l) \ No newline at end of file +where not exists(l.getLiteralObject()) +select l.getLocation().getStartLine(), repr(l) diff --git a/python/ql/test/library-tests/objects/Name.ql b/python/ql/test/library-tests/objects/Name.ql index 674890c01ba..c20358b9062 100644 --- a/python/ql/test/library-tests/objects/Name.ql +++ b/python/ql/test/library-tests/objects/Name.ql @@ -1,21 +1,21 @@ - import python from Object o, string name -where o.hasLongName(name) -and ( - name = "sys.modules" - or - name = "test.n" - or - name = "test.l" - or - name = "test.d" - or - name = "test.C.meth" - or - name = "test.C.cmeth" - or - name = "test.C.smeth" -) +where + o.hasLongName(name) and + ( + name = "sys.modules" + or + name = "test.n" + or + name = "test.l" + or + name = "test.d" + or + name = "test.C.meth" + or + name = "test.C.cmeth" + or + name = "test.C.smeth" + ) select name, o.toString() diff --git a/python/ql/test/library-tests/objects/Strings.ql b/python/ql/test/library-tests/objects/Strings.ql index 9fcceb58fe4..eca8dec51fd 100644 --- a/python/ql/test/library-tests/objects/Strings.ql +++ b/python/ql/test/library-tests/objects/Strings.ql @@ -1,8 +1,5 @@ - import python - from StringObject s, ControlFlowNode f where f.refersTo(s) select f.getLocation().toString(), s.getText() - diff --git a/python/ql/test/library-tests/parameters/Annotations.ql b/python/ql/test/library-tests/parameters/Annotations.ql index cceecd699f3..17b02844a44 100644 --- a/python/ql/test/library-tests/parameters/Annotations.ql +++ b/python/ql/test/library-tests/parameters/Annotations.ql @@ -1,6 +1,4 @@ - import python - from Parameter p select p.getName(), p.getAnnotation() diff --git a/python/ql/test/library-tests/parameters/Defaults.ql b/python/ql/test/library-tests/parameters/Defaults.ql index ab16913804d..ebc8215074b 100644 --- a/python/ql/test/library-tests/parameters/Defaults.ql +++ b/python/ql/test/library-tests/parameters/Defaults.ql @@ -1,6 +1,4 @@ - import python - from Parameter p select p.getName(), p.getDefault() diff --git a/python/ql/test/library-tests/parameters/Special.ql b/python/ql/test/library-tests/parameters/Special.ql index ff06b8f072d..4987599bc72 100644 --- a/python/ql/test/library-tests/parameters/Special.ql +++ b/python/ql/test/library-tests/parameters/Special.ql @@ -1,13 +1,10 @@ - - import python from Parameter p, string type where -p.isKwargs() and type = "kwargs" -or -p.isVarargs() and type = "varargs" -or -not p.isKwargs() and not p.isVarargs() and type = "normal" - + p.isKwargs() and type = "kwargs" + or + p.isVarargs() and type = "varargs" + or + not p.isKwargs() and not p.isVarargs() and type = "normal" select p.getName(), type diff --git a/python/ql/test/library-tests/regex/Alternation.ql b/python/ql/test/library-tests/regex/Alternation.ql index 210d26aad98..79622fae32e 100644 --- a/python/ql/test/library-tests/regex/Alternation.ql +++ b/python/ql/test/library-tests/regex/Alternation.ql @@ -1,8 +1,7 @@ - import python import semmle.python.regex from Regex r, int start, int end, int part_start, int part_end where r.alternationOption(start, end, part_start, part_end) -select r.getText(), start, end, r.getText().substring(start, end), - part_start, part_end, r.getText().substring(part_start, part_end) +select r.getText(), start, end, r.getText().substring(start, end), part_start, part_end, + r.getText().substring(part_start, part_end) diff --git a/python/ql/test/library-tests/regex/Characters.ql b/python/ql/test/library-tests/regex/Characters.ql index 38976fcf7c7..1444c37cd57 100644 --- a/python/ql/test/library-tests/regex/Characters.ql +++ b/python/ql/test/library-tests/regex/Characters.ql @@ -3,12 +3,9 @@ * @description Test for escaped characters */ - import python import semmle.python.regex from Regex r, int start, int end where r.character(start, end) and r.getLocation().getFile().getBaseName() = "test.py" select r.getText(), start, end - - diff --git a/python/ql/test/library-tests/regex/FirstLast.ql b/python/ql/test/library-tests/regex/FirstLast.ql index 0ca7e10cd3a..7a57eb51382 100644 --- a/python/ql/test/library-tests/regex/FirstLast.ql +++ b/python/ql/test/library-tests/regex/FirstLast.ql @@ -1,10 +1,8 @@ - - import python import semmle.python.regex predicate part(Regex r, int start, int end, string kind) { - r.lastItem(start, end) and kind = "last" + r.lastItem(start, end) and kind = "last" or r.firstItem(start, end) and kind = "first" } diff --git a/python/ql/test/library-tests/regex/GroupContents.ql b/python/ql/test/library-tests/regex/GroupContents.ql index 1b49f5d9efd..28ad5749c0a 100644 --- a/python/ql/test/library-tests/regex/GroupContents.ql +++ b/python/ql/test/library-tests/regex/GroupContents.ql @@ -1,8 +1,7 @@ - import python import semmle.python.regex from Regex r, int start, int end, int part_start, int part_end where r.groupContents(start, end, part_start, part_end) -select r.getText(), start, end, r.getText().substring(start, end), - part_start, part_end, r.getText().substring(part_start, part_end) \ No newline at end of file +select r.getText(), start, end, r.getText().substring(start, end), part_start, part_end, + r.getText().substring(part_start, part_end) diff --git a/python/ql/test/library-tests/regex/Mode.ql b/python/ql/test/library-tests/regex/Mode.ql index 7fd593075a9..02e84f86c5d 100644 --- a/python/ql/test/library-tests/regex/Mode.ql +++ b/python/ql/test/library-tests/regex/Mode.ql @@ -1,7 +1,4 @@ - import python - - import semmle.python.regex from Regex r diff --git a/python/ql/test/library-tests/regex/Qualified.ql b/python/ql/test/library-tests/regex/Qualified.ql index e40d2bf6ae7..8adf7e0426c 100644 --- a/python/ql/test/library-tests/regex/Qualified.ql +++ b/python/ql/test/library-tests/regex/Qualified.ql @@ -1,5 +1,3 @@ - - import python import semmle.python.regex diff --git a/python/ql/test/library-tests/regex/Regex.ql b/python/ql/test/library-tests/regex/Regex.ql index 220efdb4cc3..708ad82804d 100644 --- a/python/ql/test/library-tests/regex/Regex.ql +++ b/python/ql/test/library-tests/regex/Regex.ql @@ -1,10 +1,8 @@ - - import python import semmle.python.regex predicate part(Regex r, int start, int end, string kind) { - r.alternation(start, end) and kind = "choice" + r.alternation(start, end) and kind = "choice" or r.normalCharacter(start, end) and kind = "char" or diff --git a/python/ql/test/library-tests/scopes/Previous.ql b/python/ql/test/library-tests/scopes/Previous.ql index 1e7d25d7da8..00bd2b90f2a 100644 --- a/python/ql/test/library-tests/scopes/Previous.ql +++ b/python/ql/test/library-tests/scopes/Previous.ql @@ -2,4 +2,4 @@ import python from Scope s1, Scope s2 where s1.precedes(s2) -select s1.toString(), s2.toString() \ No newline at end of file +select s1.toString(), s2.toString() diff --git a/python/ql/test/library-tests/security/sensitive/Sources.ql b/python/ql/test/library-tests/security/sensitive/Sources.ql index f974c18780a..b5328a9f105 100644 --- a/python/ql/test/library-tests/security/sensitive/Sources.ql +++ b/python/ql/test/library-tests/security/sensitive/Sources.ql @@ -1,6 +1,4 @@ - import python - import semmle.python.security.SensitiveData from SensitiveData::Source src diff --git a/python/ql/test/library-tests/state_tracking/Test.ql b/python/ql/test/library-tests/state_tracking/Test.ql index e88365aad94..cfdfa7c77aa 100644 --- a/python/ql/test/library-tests/state_tracking/Test.ql +++ b/python/ql/test/library-tests/state_tracking/Test.ql @@ -1,14 +1,12 @@ - import python import Lib from ControlFlowNode f, TrackableState state, Context ctx, boolean sense where -f.getLocation().getStartLine() >= 20 and -( - state.appliesTo(f, ctx) and sense = true - or - state.mayNotApplyTo(f, ctx) and sense = false -) - + f.getLocation().getStartLine() >= 20 and + ( + state.appliesTo(f, ctx) and sense = true + or + state.mayNotApplyTo(f, ctx) and sense = false + ) select f.getLocation().toString(), f, ctx, state, sense diff --git a/python/ql/test/library-tests/state_tracking/Violations.ql b/python/ql/test/library-tests/state_tracking/Violations.ql index 8da2a0500ef..db70e7d3368 100644 --- a/python/ql/test/library-tests/state_tracking/Violations.ql +++ b/python/ql/test/library-tests/state_tracking/Violations.ql @@ -1,15 +1,12 @@ - import python import Lib from ControlFlowNode f, TrackableState state where -( - callTo(f, "exacerbate") and state = "frobnicated" - or - callTo(f, "frobnicate") and state = "initialized" -) -and -state.mayNotApplyTo(f) - + ( + callTo(f, "exacerbate") and state = "frobnicated" + or + callTo(f, "frobnicate") and state = "initialized" + ) and + state.mayNotApplyTo(f) select f.getLocation().toString(), f.toString(), state.toString() diff --git a/python/ql/test/library-tests/stmts/general/AstParent.ql b/python/ql/test/library-tests/stmts/general/AstParent.ql index b7ea6f44ac3..85e0f4947fa 100644 --- a/python/ql/test/library-tests/stmts/general/AstParent.ql +++ b/python/ql/test/library-tests/stmts/general/AstParent.ql @@ -1,8 +1,5 @@ import python /* The result of this query should always be 0, *regardless* of the database. */ - -select -count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) -+ -count(AstNode c | strictcount(c.getParentNode()) > 1) +select count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) + + count(AstNode c | strictcount(c.getParentNode()) > 1) diff --git a/python/ql/test/library-tests/stmts/general/SubExpressions.ql b/python/ql/test/library-tests/stmts/general/SubExpressions.ql index deaff1e9610..e3b5eed1ced 100644 --- a/python/ql/test/library-tests/stmts/general/SubExpressions.ql +++ b/python/ql/test/library-tests/stmts/general/SubExpressions.ql @@ -1,5 +1,5 @@ - import python from Stmt s -select s.toString(), s.getASubExpression().toString(), s.getASubExpression().getASubExpression*().toString(), s.getLocation().getStartLine() \ No newline at end of file +select s.toString(), s.getASubExpression().toString(), + s.getASubExpression().getASubExpression*().toString(), s.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/stmts/raise_stmt/AST.ql b/python/ql/test/library-tests/stmts/raise_stmt/AST.ql index d9daaa8514b..62719f1179f 100644 --- a/python/ql/test/library-tests/stmts/raise_stmt/AST.ql +++ b/python/ql/test/library-tests/stmts/raise_stmt/AST.ql @@ -1,7 +1,6 @@ - - import python from AstNode parent, AstNode child where child.getParentNode() = parent -select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), child.toString() \ No newline at end of file +select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), + child.toString() diff --git a/python/ql/test/library-tests/stmts/try_stmt/AST.ql b/python/ql/test/library-tests/stmts/try_stmt/AST.ql index d9daaa8514b..62719f1179f 100644 --- a/python/ql/test/library-tests/stmts/try_stmt/AST.ql +++ b/python/ql/test/library-tests/stmts/try_stmt/AST.ql @@ -1,7 +1,6 @@ - - import python from AstNode parent, AstNode child where child.getParentNode() = parent -select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), child.toString() \ No newline at end of file +select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), + child.toString() diff --git a/python/ql/test/library-tests/stmts/with_stmt/AST.ql b/python/ql/test/library-tests/stmts/with_stmt/AST.ql index d9daaa8514b..62719f1179f 100644 --- a/python/ql/test/library-tests/stmts/with_stmt/AST.ql +++ b/python/ql/test/library-tests/stmts/with_stmt/AST.ql @@ -1,7 +1,6 @@ - - import python from AstNode parent, AstNode child where child.getParentNode() = parent -select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), child.toString() \ No newline at end of file +select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), + child.toString() diff --git a/python/ql/test/library-tests/taint/collections/TestTaint.ql b/python/ql/test/library-tests/taint/collections/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/collections/TestTaint.ql +++ b/python/ql/test/library-tests/taint/collections/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/config/RockPaperScissors.ql b/python/ql/test/library-tests/taint/config/RockPaperScissors.ql index 0910f9846c4..311039a6553 100644 --- a/python/ql/test/library-tests/taint/config/RockPaperScissors.ql +++ b/python/ql/test/library-tests/taint/config/RockPaperScissors.ql @@ -1,4 +1,3 @@ - /** * @kind path-problem */ @@ -10,4 +9,5 @@ import semmle.python.security.Paths from RockPaperScissorConfig config, TaintedPathSource src, TaintedPathSink sink where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "$@ loses to $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), sink.getTaintKind().toString() \ No newline at end of file +select sink.getSink(), src, sink, "$@ loses to $@.", src.getNode(), src.getTaintKind().toString(), + sink.getNode(), sink.getTaintKind().toString() diff --git a/python/ql/test/library-tests/taint/config/Simple.ql b/python/ql/test/library-tests/taint/config/Simple.ql index a3acf7272f6..76e8c261048 100644 --- a/python/ql/test/library-tests/taint/config/Simple.ql +++ b/python/ql/test/library-tests/taint/config/Simple.ql @@ -1,4 +1,3 @@ - /** * @kind path-problem */ @@ -10,4 +9,5 @@ import semmle.python.security.Paths from SimpleConfig config, TaintedPathSource src, TaintedPathSink sink where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "$@ flows to $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), sink.getTaintKind().toString() +select sink.getSink(), src, sink, "$@ flows to $@.", src.getNode(), src.getTaintKind().toString(), + sink.getNode(), sink.getTaintKind().toString() diff --git a/python/ql/test/library-tests/taint/config/TaintedArgument.ql b/python/ql/test/library-tests/taint/config/TaintedArgument.ql index 9cbde79561b..ca351d878a5 100644 --- a/python/ql/test/library-tests/taint/config/TaintedArgument.ql +++ b/python/ql/test/library-tests/taint/config/TaintedArgument.ql @@ -1,14 +1,12 @@ - import python - - - import semmle.python.security.TaintTracking import TaintLib import semmle.python.dataflow.Implementation -from TaintTrackingImplementation config, TaintTrackingNode src, CallNode call, - TaintTrackingContext caller, CallableValue pyfunc, int arg, AttributePath path, TaintKind kind -where config instanceof TestConfig and -config.callWithTaintedArgument(src, call, caller, pyfunc, arg, path, kind) +from + TaintTrackingImplementation config, TaintTrackingNode src, CallNode call, + TaintTrackingContext caller, CallableValue pyfunc, int arg, AttributePath path, TaintKind kind +where + config instanceof TestConfig and + config.callWithTaintedArgument(src, call, caller, pyfunc, arg, path, kind) select config, src, call, caller, pyfunc, arg, path, kind diff --git a/python/ql/test/library-tests/taint/config/TestNode.ql b/python/ql/test/library-tests/taint/config/TestNode.ql index 165bf382301..02a4dd278c3 100644 --- a/python/ql/test/library-tests/taint/config/TestNode.ql +++ b/python/ql/test/library-tests/taint/config/TestNode.ql @@ -3,8 +3,7 @@ import semmle.python.security.TaintTracking import semmle.python.dataflow.Implementation import TaintLib - from TaintTrackingNode n where n.getConfiguration() instanceof TestConfig -select n.getLocation().toString(), n.getTaintKind(), n.getNode().toString(), n.getPath().toString(), n.getContext().toString() - +select n.getLocation().toString(), n.getTaintKind(), n.getNode().toString(), n.getPath().toString(), + n.getContext().toString() diff --git a/python/ql/test/library-tests/taint/config/TestSink.ql b/python/ql/test/library-tests/taint/config/TestSink.ql index 2fc42bce378..4df3f48b939 100644 --- a/python/ql/test/library-tests/taint/config/TestSink.ql +++ b/python/ql/test/library-tests/taint/config/TestSink.ql @@ -3,6 +3,5 @@ import semmle.python.security.TaintTracking import TaintLib from TestConfig config, DataFlow::Node sink, TaintKind kind - where config.isSink(sink, kind) select sink.getLocation().toString(), config, sink.toString(), kind diff --git a/python/ql/test/library-tests/taint/config/TestSource.ql b/python/ql/test/library-tests/taint/config/TestSource.ql index 338ec65fd45..191583becb7 100644 --- a/python/ql/test/library-tests/taint/config/TestSource.ql +++ b/python/ql/test/library-tests/taint/config/TestSource.ql @@ -3,6 +3,6 @@ import semmle.python.security.TaintTracking import TaintLib from TestConfig config, DataFlow::Node source, TaintKind kind - where config.isSource(source, kind) -select config, source.getLocation().toString(), source.getLocation().getStartLine(), source.toString(), kind +select config, source.getLocation().toString(), source.getLocation().getStartLine(), + source.toString(), kind diff --git a/python/ql/test/library-tests/taint/config/TestStep.ql b/python/ql/test/library-tests/taint/config/TestStep.ql index 2f702834d01..f16f2e36bb8 100644 --- a/python/ql/test/library-tests/taint/config/TestStep.ql +++ b/python/ql/test/library-tests/taint/config/TestStep.ql @@ -3,11 +3,8 @@ import semmle.python.security.TaintTracking import TaintLib import semmle.python.dataflow.Implementation - from TaintTrackingNode n, TaintTrackingNode s, TestConfig config where s = n.getASuccessor() and config = n.getConfiguration() -select - config + ":", - n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), - " --> ", - s.getTaintKind(), s.getLocation().toString(), s.getNode().toString(), s.getContext() +select config + ":", n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), + n.getContext(), " --> ", s.getTaintKind(), s.getLocation().toString(), s.getNode().toString(), + s.getContext() diff --git a/python/ql/test/library-tests/taint/dataflow/Dataflow.ql b/python/ql/test/library-tests/taint/dataflow/Dataflow.ql index d758f32b2df..ced8b9a7c25 100644 --- a/python/ql/test/library-tests/taint/dataflow/Dataflow.ql +++ b/python/ql/test/library-tests/taint/dataflow/Dataflow.ql @@ -1,4 +1,3 @@ - import python import Config diff --git a/python/ql/test/library-tests/taint/dataflow/TestNode.ql b/python/ql/test/library-tests/taint/dataflow/TestNode.ql index 81bb0c0fc56..3498d5546da 100644 --- a/python/ql/test/library-tests/taint/dataflow/TestNode.ql +++ b/python/ql/test/library-tests/taint/dataflow/TestNode.ql @@ -2,4 +2,5 @@ import python import Config from TaintedNode n -select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), n.getContext() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), + n.getContext() diff --git a/python/ql/test/library-tests/taint/example/Edges.ql b/python/ql/test/library-tests/taint/example/Edges.ql index 4b975666d92..0674f3a073c 100644 --- a/python/ql/test/library-tests/taint/example/Edges.ql +++ b/python/ql/test/library-tests/taint/example/Edges.ql @@ -3,18 +3,24 @@ import semmle.python.security.TaintTracking import semmle.python.dataflow.Implementation import DilbertConfig - string shortString(TaintTrackingNode n) { - if n.getContext().isTop() then - result = n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + " = " + n.getTaintKind() + if n.getContext().isTop() + then + result = + n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + + " = " + n.getTaintKind() else - result = n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + " = " + n.getTaintKind() + " (" + n.getContext().toString() + ")" + result = + n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + + " = " + n.getTaintKind() + " (" + n.getContext().toString() + ")" } bindingset[s, len] string ljust(string s, int len) { - result = s + - " ".prefix(len-s.length()) + result = + s + + " " + .prefix(len - s.length()) } bindingset[s, len] @@ -23,7 +29,7 @@ string format(string s, int len) { s = "" and label = "[dataflow]" or s != "" and label = s - | + | result = ljust(label, len) ) } @@ -31,4 +37,3 @@ string format(string s, int len) { from TaintTrackingNode p, TaintTrackingNode s, string label where any(DilbertConfig config).(TaintTrackingImplementation).flowStep(p, s, label) select format(shortString(p), 50), format(label, 10), shortString(s) - diff --git a/python/ql/test/library-tests/taint/example/ExampleConfig.ql b/python/ql/test/library-tests/taint/example/ExampleConfig.ql index cb0c43de3d1..e3809c7a024 100644 --- a/python/ql/test/library-tests/taint/example/ExampleConfig.ql +++ b/python/ql/test/library-tests/taint/example/ExampleConfig.ql @@ -1,6 +1,6 @@ /** * @kind path-problem - * + * * An example configuration. * See ExampleConfiguration.expected for the results of running this query. */ @@ -9,7 +9,7 @@ import python import DilbertConfig import semmle.python.security.Paths - from DilbertConfig config, TaintedPathSource src, TaintedPathSink sink where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "$@ goes to a $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), "meeting" +select sink.getSink(), src, sink, "$@ goes to a $@.", src.getNode(), src.getTaintKind().toString(), + sink.getNode(), "meeting" diff --git a/python/ql/test/library-tests/taint/example/Nodes.ql b/python/ql/test/library-tests/taint/example/Nodes.ql index 21e315bca74..0a5ff02c2a3 100644 --- a/python/ql/test/library-tests/taint/example/Nodes.ql +++ b/python/ql/test/library-tests/taint/example/Nodes.ql @@ -3,8 +3,7 @@ import semmle.python.security.TaintTracking import semmle.python.dataflow.Implementation import DilbertConfig - from TaintTrackingNode n where n.getConfiguration() instanceof DilbertConfig -select n.getLocation().toString(), n.getNode().toString(), n.getPath().toString(), n.getContext().toString(), n.getTaintKind() - +select n.getLocation().toString(), n.getNode().toString(), n.getPath().toString(), + n.getContext().toString(), n.getTaintKind() diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql b/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql index b9ec3c2ff3e..b11ef5e18e8 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql +++ b/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql @@ -1,8 +1,7 @@ import python - import semmle.python.security.Exceptions import semmle.python.web.HttpResponse from TaintedNode node where not node.getLocation().getFile().inStdlib() -select node.getLocation(), node.getNode().getNode().toString(), node.getTaintKind() \ No newline at end of file +select node.getLocation(), node.getNode().getNode().toString(), node.getTaintKind() diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql b/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql index 8e625641b77..d66d80dae40 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql +++ b/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql @@ -1,11 +1,9 @@ import python - import semmle.python.security.Exceptions import semmle.python.web.HttpResponse - from TaintSource src, TaintKind kind -where - src.isSourceOf(kind) and +where + src.isSourceOf(kind) and not src.getLocation().getFile().inStdlib() -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind \ No newline at end of file +select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql b/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql index 8354e2526f5..6d10a7c5ed3 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql +++ b/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql @@ -1,5 +1,4 @@ import python - import semmle.python.security.Exceptions import semmle.python.web.HttpResponse @@ -8,7 +7,6 @@ where s = n.getASuccessor() and not n.getLocation().getFile().inStdlib() and not s.getLocation().getFile().inStdlib() -select - "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), - " --> ", - "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getNode().toString(), s.getContext() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), + n.getContext(), " --> ", "Taint " + s.getTaintKind(), s.getLocation().toString(), + s.getNode().toString(), s.getContext() diff --git a/python/ql/test/library-tests/taint/extensions/TestNode.ql b/python/ql/test/library-tests/taint/extensions/TestNode.ql index 842c63186ba..2fa17776be3 100644 --- a/python/ql/test/library-tests/taint/extensions/TestNode.ql +++ b/python/ql/test/library-tests/taint/extensions/TestNode.ql @@ -1,8 +1,6 @@ import python - import ExtensionsLib - from TaintedNode n -select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), n.getContext() - +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), + n.getContext() diff --git a/python/ql/test/library-tests/taint/extensions/TestStep.ql b/python/ql/test/library-tests/taint/extensions/TestStep.ql index 95003b44270..9005aba858e 100644 --- a/python/ql/test/library-tests/taint/extensions/TestStep.ql +++ b/python/ql/test/library-tests/taint/extensions/TestStep.ql @@ -1,11 +1,8 @@ import python - import ExtensionsLib - from TaintedNode n, TaintedNode s where s = n.getASuccessor() -select - "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), n.getContext(), - " --> ", - "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getNode().getNode().toString(), s.getContext() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), + n.getContext(), " --> ", "Taint " + s.getTaintKind(), s.getLocation().toString(), + s.getNode().getNode().toString(), s.getContext() diff --git a/python/ql/test/library-tests/taint/general/Contexts.ql b/python/ql/test/library-tests/taint/general/Contexts.ql index 9d3d7ec6c32..6eee5f449b2 100644 --- a/python/ql/test/library-tests/taint/general/Contexts.ql +++ b/python/ql/test/library-tests/taint/general/Contexts.ql @@ -1,10 +1,9 @@ - import python import semmle.python.dataflow.Implementation import TaintLib from CallContext context, Scope s -where exists(CallContext caller | caller.getCallee(_) = context) and -context.appliesToScope(s) +where + exists(CallContext caller | caller.getCallee(_) = context) and + context.appliesToScope(s) select s.getLocation().toString(), context, s.toString() - diff --git a/python/ql/test/library-tests/taint/general/ModuleAttribute.ql b/python/ql/test/library-tests/taint/general/ModuleAttribute.ql index 25831de268d..6a4349b4100 100644 --- a/python/ql/test/library-tests/taint/general/ModuleAttribute.ql +++ b/python/ql/test/library-tests/taint/general/ModuleAttribute.ql @@ -2,8 +2,6 @@ import python import semmle.python.dataflow.Implementation import TaintLib - from ModuleValue m, string name, TaintedNode origin, TaintTrackingImplementation impl where impl.moduleAttributeTainted(m, name, origin) - select m.toString(), name, origin.toString(), origin.getContext(), origin.getLocation().toString() diff --git a/python/ql/test/library-tests/taint/general/ParamSource.ql b/python/ql/test/library-tests/taint/general/ParamSource.ql index 664fd8b77e5..f0956d0333d 100644 --- a/python/ql/test/library-tests/taint/general/ParamSource.ql +++ b/python/ql/test/library-tests/taint/general/ParamSource.ql @@ -1,37 +1,26 @@ import python import semmle.python.security.TaintTracking - /* Standard library sink */ import semmle.python.security.injection.Command class TestKind extends TaintKind { - TestKind() { - this = "test" - } - + TestKind() { this = "test" } } class CustomSource extends TaintSource { - CustomSource() { - exists(Parameter p | + exists(Parameter p | p.asName().getId() = "arg" and this.(ControlFlowNode).getNode() = p ) } - override predicate isSourceOf(TaintKind kind) { - kind instanceof TestKind - } - - override string toString() { - result = "Source of untrusted input" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof TestKind } + override string toString() { result = "Source of untrusted input" } } class SimpleSink extends TaintSink { - override string toString() { result = "Simple sink" } SimpleSink() { @@ -41,13 +30,10 @@ class SimpleSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof TestKind - } - + override predicate sinks(TaintKind taint) { taint instanceof TestKind } } from TaintSource src, TaintSink sink, TaintKind srckind, TaintKind sinkkind - where src.flowsToSink(srckind, sink) and sink.sinks(sinkkind) -select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), sink.(ControlFlowNode).getNode().toString(), sinkkind +select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), + sink.(ControlFlowNode).getNode().toString(), sinkkind diff --git a/python/ql/test/library-tests/taint/general/TaintSanity.ql b/python/ql/test/library-tests/taint/general/TaintSanity.ql index ddfa5a3af32..d07828e5947 100644 --- a/python/ql/test/library-tests/taint/general/TaintSanity.ql +++ b/python/ql/test/library-tests/taint/general/TaintSanity.ql @@ -3,24 +3,27 @@ import semmle.python.dataflow.TaintTracking import semmle.python.dataflow.Implementation import TaintLib -from TaintKind taint, TaintTrackingContext c, DataFlow::Node n, string what, TaintTrackingImplementation impl +from + TaintKind taint, TaintTrackingContext c, DataFlow::Node n, string what, + TaintTrackingImplementation impl where -not exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c) and -( - impl.flowStep(_, n, c, _, taint, _) and what = "missing node at end of step" + not exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c) and + ( + impl.flowStep(_, n, c, _, taint, _) and what = "missing node at end of step" + or + impl.flowSource(n, c, _, taint) and what = "missing node for source" + ) or - impl.flowSource(n, c, _, taint) and what = "missing node for source" -) -or -exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c - | - not impl.flowStep(_, n, c, _, taint, _) and - not impl.flowSource(n, c, _, taint) and what = "TaintedNode with no reason" - or - impl.flowStep(t, n, c, _, taint, _) and what = "step ends where it starts" - or - impl.flowStep(t, _, _, _, _, _) and not impl.flowStep(_, n, c, _, taint, _) and - not impl.flowSource(n, c, _, taint) and what = "No predecessor and not a source" -) - + exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c | + not impl.flowStep(_, n, c, _, taint, _) and + not impl.flowSource(n, c, _, taint) and + what = "TaintedNode with no reason" + or + impl.flowStep(t, n, c, _, taint, _) and what = "step ends where it starts" + or + impl.flowStep(t, _, _, _, _, _) and + not impl.flowStep(_, n, c, _, taint, _) and + not impl.flowSource(n, c, _, taint) and + what = "No predecessor and not a source" + ) select n.getLocation(), taint, c, n.toString(), what diff --git a/python/ql/test/library-tests/taint/general/TestDefn.ql b/python/ql/test/library-tests/taint/general/TestDefn.ql index e793d24649b..e2791bf2e72 100644 --- a/python/ql/test/library-tests/taint/general/TestDefn.ql +++ b/python/ql/test/library-tests/taint/general/TestDefn.ql @@ -1,8 +1,7 @@ import python import TaintLib - from EssaNodeDefinition defn, TaintedNode n where n.getNode().asVariable() = defn.getVariable() -select - defn.getLocation().toString(), defn.getRepresentation(), n.getLocation().toString(), "Taint " + n.toString(), defn.getDefiningNode().getNode().toString() +select defn.getLocation().toString(), defn.getRepresentation(), n.getLocation().toString(), + "Taint " + n.toString(), defn.getDefiningNode().getNode().toString() diff --git a/python/ql/test/library-tests/taint/general/TestSanitizers.ql b/python/ql/test/library-tests/taint/general/TestSanitizers.ql index 3dca04d581e..cee31378f7d 100644 --- a/python/ql/test/library-tests/taint/general/TestSanitizers.ql +++ b/python/ql/test/library-tests/taint/general/TestSanitizers.ql @@ -1,4 +1,3 @@ - import python import semmle.python.security.TaintTracking import TaintLib @@ -6,5 +5,3 @@ import TaintLib from Sanitizer s, TaintKind taint, PyEdgeRefinement test where s.sanitizingEdge(taint, test) select s, taint, test.getLocation().toString(), test.getRepresentation() - - diff --git a/python/ql/test/library-tests/taint/general/TestSink.ql b/python/ql/test/library-tests/taint/general/TestSink.ql index d0361cc204a..422527fbee2 100644 --- a/python/ql/test/library-tests/taint/general/TestSink.ql +++ b/python/ql/test/library-tests/taint/general/TestSink.ql @@ -3,6 +3,6 @@ import semmle.python.security.TaintTracking import TaintLib from TaintSource src, TaintSink sink, TaintKind srckind, TaintKind sinkkind - where src.flowsToSink(srckind, sink) and sink.sinks(sinkkind) -select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), sink.(ControlFlowNode).getNode().toString(), sinkkind +select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), + sink.(ControlFlowNode).getNode().toString(), sinkkind diff --git a/python/ql/test/library-tests/taint/general/TestSource.ql b/python/ql/test/library-tests/taint/general/TestSource.ql index ba064220bfb..d71bab289e0 100644 --- a/python/ql/test/library-tests/taint/general/TestSource.ql +++ b/python/ql/test/library-tests/taint/general/TestSource.ql @@ -2,7 +2,6 @@ import python import semmle.python.security.TaintTracking import TaintLib - from TaintSource src, TaintKind kind where src.isSourceOf(kind) select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/taint/general/TestStep.ql b/python/ql/test/library-tests/taint/general/TestStep.ql index 710b180501d..c6de9cad361 100644 --- a/python/ql/test/library-tests/taint/general/TestStep.ql +++ b/python/ql/test/library-tests/taint/general/TestStep.ql @@ -2,11 +2,7 @@ import python import semmle.python.security.TaintTracking import TaintLib - from TaintedNode n, TaintedNode s -where - s = n.getASuccessor() -select - n.toString(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), - "-->", +where s = n.getASuccessor() +select n.toString(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), "-->", s.toString(), s.getLocation().toString(), s.getNode().toString(), s.getContext() diff --git a/python/ql/test/library-tests/taint/general/TestTaint.ql b/python/ql/test/library-tests/taint/general/TestTaint.ql index 3b8bf2b4bde..904cbbbded9 100644 --- a/python/ql/test/library-tests/taint/general/TestTaint.ql +++ b/python/ql/test/library-tests/taint/general/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/general/TestVar.ql b/python/ql/test/library-tests/taint/general/TestVar.ql index b90760f55ce..991d3cdbfa4 100644 --- a/python/ql/test/library-tests/taint/general/TestVar.ql +++ b/python/ql/test/library-tests/taint/general/TestVar.ql @@ -1,8 +1,7 @@ import python import TaintLib - from EssaVariable var, TaintedNode n where n.getNode().asVariable() = var -select - var.getDefinition().getLocation().toString(), var.getRepresentation(), n.getLocation().toString(), "Taint " + n.toString() +select var.getDefinition().getLocation().toString(), var.getRepresentation(), + n.getLocation().toString(), "Taint " + n.toString() diff --git a/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql b/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql +++ b/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/strings/TestStep.ql b/python/ql/test/library-tests/taint/strings/TestStep.ql index abec09b20d6..e7c014f2eb2 100644 --- a/python/ql/test/library-tests/taint/strings/TestStep.ql +++ b/python/ql/test/library-tests/taint/strings/TestStep.ql @@ -2,12 +2,10 @@ import python import semmle.python.security.TaintTracking import Taint - from TaintedNode n, TaintedNode s -where n.getLocation().getFile().getShortName() = "test.py" and -s.getLocation().getFile().getShortName() = "test.py" and -s = n.getASuccessor() -select - "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getAstNode(), n.getContext(), - " --> ", - "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getAstNode(), s.getContext() +where + n.getLocation().getFile().getShortName() = "test.py" and + s.getLocation().getFile().getShortName() = "test.py" and + s = n.getASuccessor() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getAstNode(), n.getContext(), + " --> ", "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getAstNode(), s.getContext() diff --git a/python/ql/test/library-tests/taint/strings/TestTaint.ql b/python/ql/test/library-tests/taint/strings/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/strings/TestTaint.ql +++ b/python/ql/test/library-tests/taint/strings/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/unpacking/TestTaint.ql b/python/ql/test/library-tests/taint/unpacking/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/unpacking/TestTaint.ql +++ b/python/ql/test/library-tests/taint/unpacking/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/thrift/Child.ql b/python/ql/test/library-tests/thrift/Child.ql index 5645c53ddb0..ebe72889aad 100644 --- a/python/ql/test/library-tests/thrift/Child.ql +++ b/python/ql/test/library-tests/thrift/Child.ql @@ -1,4 +1,3 @@ - import external.Thrift from ThriftElement t, int n diff --git a/python/ql/test/library-tests/thrift/File.ql b/python/ql/test/library-tests/thrift/File.ql index e4f497dbd01..7d85dd40ca4 100644 --- a/python/ql/test/library-tests/thrift/File.ql +++ b/python/ql/test/library-tests/thrift/File.ql @@ -1,7 +1,4 @@ - import external.Thrift - from ThriftNamedElement t - -select t.getName(), t.getFile().getBaseName() \ No newline at end of file +select t.getName(), t.getFile().getBaseName() diff --git a/python/ql/test/library-tests/thrift/Function.ql b/python/ql/test/library-tests/thrift/Function.ql index ff891bd5ece..2161fd8ec8a 100644 --- a/python/ql/test/library-tests/thrift/Function.ql +++ b/python/ql/test/library-tests/thrift/Function.ql @@ -1,12 +1,10 @@ - import external.Thrift from ThriftFunction t, string n, ThriftElement x where -exists(int i | x = t.getArgument(i) and n = i.toString()) -or -x = t.getAThrows() and n = "throws" -or -x = t.getReturnType() and n = "returns" - -select t, n, x \ No newline at end of file + exists(int i | x = t.getArgument(i) and n = i.toString()) + or + x = t.getAThrows() and n = "throws" + or + x = t.getReturnType() and n = "returns" +select t, n, x diff --git a/python/ql/test/library-tests/thrift/References.ql b/python/ql/test/library-tests/thrift/References.ql index c6621b44e95..f40e6e0a74b 100644 --- a/python/ql/test/library-tests/thrift/References.ql +++ b/python/ql/test/library-tests/thrift/References.ql @@ -1,4 +1,3 @@ - import python import external.Thrift diff --git a/python/ql/test/library-tests/thrift/Service.ql b/python/ql/test/library-tests/thrift/Service.ql index 801379c6a2e..3f3b07e0bc0 100644 --- a/python/ql/test/library-tests/thrift/Service.ql +++ b/python/ql/test/library-tests/thrift/Service.ql @@ -1,6 +1,4 @@ - import external.Thrift - from ThriftService service, string name select service, name, service.getFunction(name) diff --git a/python/ql/test/library-tests/thrift/Test.ql b/python/ql/test/library-tests/thrift/Test.ql index 735b9ad0eae..d755d9f1d26 100644 --- a/python/ql/test/library-tests/thrift/Test.ql +++ b/python/ql/test/library-tests/thrift/Test.ql @@ -1,7 +1,5 @@ - import external.Thrift from string cls where any(ThriftElement t).getAQlClass() = cls select cls.prefix(6) - diff --git a/python/ql/test/library-tests/thrift/Value.ql b/python/ql/test/library-tests/thrift/Value.ql index 7cf83b1df65..b42ae96d6ca 100644 --- a/python/ql/test/library-tests/thrift/Value.ql +++ b/python/ql/test/library-tests/thrift/Value.ql @@ -1,5 +1,4 @@ - import external.Thrift from ThriftElement t -select t, t.getValue() \ No newline at end of file +select t, t.getValue() diff --git a/python/ql/test/library-tests/types/attributes/Test.ql b/python/ql/test/library-tests/types/attributes/Test.ql index a92064a2551..a012b0d3a15 100644 --- a/python/ql/test/library-tests/types/attributes/Test.ql +++ b/python/ql/test/library-tests/types/attributes/Test.ql @@ -2,5 +2,5 @@ import python from ClassObject cls, ClassObject start, string name, Object val where not name.substring(0, 2) = "__" and val = cls.lookupMro(start, name) -select -cls.getOrigin().getLocation().getStartLine(), cls.toString(), start.toString(), name, val.toString(), val.getOrigin().getLocation().getStartLine() \ No newline at end of file +select cls.getOrigin().getLocation().getStartLine(), cls.toString(), start.toString(), name, + val.toString(), val.getOrigin().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/types/classattr/ClassAttribute.ql b/python/ql/test/library-tests/types/classattr/ClassAttribute.ql index 6895020718e..6e023dcada5 100644 --- a/python/ql/test/library-tests/types/classattr/ClassAttribute.ql +++ b/python/ql/test/library-tests/types/classattr/ClassAttribute.ql @@ -8,12 +8,11 @@ import python from ClassObject cls, string name, string kind where -not cls.isC() and -not name.matches("\\_\\_%\\_\\_") and -( - cls.hasAttribute(name) and kind = "has" - or - cls.declaresAttribute(name) and kind = "declares" -) -select cls.toString(), kind ,name - + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") and + ( + cls.hasAttribute(name) and kind = "has" + or + cls.declaresAttribute(name) and kind = "declares" + ) +select cls.toString(), kind, name diff --git a/python/ql/test/library-tests/types/classattr/ClassMember.ql b/python/ql/test/library-tests/types/classattr/ClassMember.ql index b76851dd43d..1357deb0da9 100644 --- a/python/ql/test/library-tests/types/classattr/ClassMember.ql +++ b/python/ql/test/library-tests/types/classattr/ClassMember.ql @@ -7,12 +7,12 @@ import python from ClassObject cls, string name, string kind, Object o -where -not cls.isC() and -not name.matches("\\_\\_%\\_\\_") and -( - o = cls.lookupAttribute(name) and kind = "has" - or - o = cls.declaredAttribute(name) and kind = "declares" -) +where + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") and + ( + o = cls.lookupAttribute(name) and kind = "has" + or + o = cls.declaredAttribute(name) and kind = "declares" + ) select cls.toString(), kind, name, o.toString() diff --git a/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql b/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql index cdfd29b8d91..26e9ad08c26 100644 --- a/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql +++ b/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql @@ -1,14 +1,13 @@ - import python from ClassObject cls, string name, string kind, Object o -where -not cls.isC() and -name.matches("\\_\\_%\\_\\_") and -not o = theObjectType().lookupAttribute(name) and -( - o = cls.lookupAttribute(name) and kind = "has" - or - o = cls.declaredAttribute(name) and kind = "declares" -) +where + not cls.isC() and + name.matches("\\_\\_%\\_\\_") and + not o = theObjectType().lookupAttribute(name) and + ( + o = cls.lookupAttribute(name) and kind = "has" + or + o = cls.declaredAttribute(name) and kind = "declares" + ) select cls.toString(), kind, name, o.toString() diff --git a/python/ql/test/library-tests/types/classes/FailedInference.ql b/python/ql/test/library-tests/types/classes/FailedInference.ql index df5e2ccf14f..192cf696fbf 100644 --- a/python/ql/test/library-tests/types/classes/FailedInference.ql +++ b/python/ql/test/library-tests/types/classes/FailedInference.ql @@ -1,11 +1,6 @@ - import python import semmle.python.pointsto.PointsTo from ClassValue cls, string reason - -where -Types::failedInference(cls, reason) - +where Types::failedInference(cls, reason) select cls, reason - diff --git a/python/ql/test/library-tests/types/classes/duplicate_base.ql b/python/ql/test/library-tests/types/classes/duplicate_base.ql index 4f865754088..47e975c4560 100644 --- a/python/ql/test/library-tests/types/classes/duplicate_base.ql +++ b/python/ql/test/library-tests/types/classes/duplicate_base.ql @@ -1,7 +1,5 @@ - import python from ClassObject cls where cls.hasDuplicateBases() select cls.toString() - diff --git a/python/ql/test/library-tests/types/exceptions/ExitRaises.ql b/python/ql/test/library-tests/types/exceptions/ExitRaises.ql index efa1f66b8d8..62be45dce8e 100644 --- a/python/ql/test/library-tests/types/exceptions/ExitRaises.ql +++ b/python/ql/test/library-tests/types/exceptions/ExitRaises.ql @@ -2,5 +2,4 @@ import python from RaisingNode r, Scope s, ClassObject cls where r.viableExceptionalExit(s, cls) - select r.getLocation().getStartLine(), r, s.toString(), cls diff --git a/python/ql/test/library-tests/types/exceptions/Handles.ql b/python/ql/test/library-tests/types/exceptions/Handles.ql index 51ceba1a6fb..601f2632392 100644 --- a/python/ql/test/library-tests/types/exceptions/Handles.ql +++ b/python/ql/test/library-tests/types/exceptions/Handles.ql @@ -1,5 +1,3 @@ - - import python from ExceptFlowNode n, ClassObject cls diff --git a/python/ql/test/library-tests/types/exceptions/Impossible.ql b/python/ql/test/library-tests/types/exceptions/Impossible.ql index e215a7e96ca..69c658edba6 100644 --- a/python/ql/test/library-tests/types/exceptions/Impossible.ql +++ b/python/ql/test/library-tests/types/exceptions/Impossible.ql @@ -1,20 +1,19 @@ - - import python from RaisingNode r, ControlFlowNode n, string kind -where r.unlikelySuccessor(n) and -( - r.getATrueSuccessor() = n and kind = "true" - or - r.getAFalseSuccessor() = n and kind = "false" - or - r.getAnExceptionalSuccessor() = n and kind = "exceptional" - or - not r.getATrueSuccessor() = n and - not r.getAFalseSuccessor() = n and - not r.getAnExceptionalSuccessor() = n and - kind = "normal" - -) -select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), n.getNode().toString(), kind +where + r.unlikelySuccessor(n) and + ( + r.getATrueSuccessor() = n and kind = "true" + or + r.getAFalseSuccessor() = n and kind = "false" + or + r.getAnExceptionalSuccessor() = n and kind = "exceptional" + or + not r.getATrueSuccessor() = n and + not r.getAFalseSuccessor() = n and + not r.getAnExceptionalSuccessor() = n and + kind = "normal" + ) +select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), + n.getNode().toString(), kind diff --git a/python/ql/test/library-tests/types/exceptions/LineRaises.ql b/python/ql/test/library-tests/types/exceptions/LineRaises.ql index f1f51952d00..933eb8d59bb 100644 --- a/python/ql/test/library-tests/types/exceptions/LineRaises.ql +++ b/python/ql/test/library-tests/types/exceptions/LineRaises.ql @@ -1,13 +1,12 @@ - import python from RaisingNode r, string type -where +where type = r.getARaisedType().toString() or type = "Unknown" and r.raisesUnknownType() or not exists(r.getARaisedType()) and - not r.raisesUnknownType() and type = "None" - + not r.raisesUnknownType() and + type = "None" select r.getNode().getLocation().getStartLine(), type diff --git a/python/ql/test/library-tests/types/exceptions/Raises.ql b/python/ql/test/library-tests/types/exceptions/Raises.ql index b003fd03dfa..aa477f718a2 100644 --- a/python/ql/test/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/library-tests/types/exceptions/Raises.ql @@ -1,13 +1,12 @@ - import python from PyFunctionObject f, string type -where +where type = f.getARaisedType().toString() or type = "Unknown" and f.raisesUnknownType() or not exists(f.getARaisedType()) and - not f.raisesUnknownType() and type = "None" - -select f.toString(), type \ No newline at end of file + not f.raisesUnknownType() and + type = "None" +select f.toString(), type diff --git a/python/ql/test/library-tests/types/exceptions/Reraises.ql b/python/ql/test/library-tests/types/exceptions/Reraises.ql index 9edcdf57b4b..699eb325f8c 100644 --- a/python/ql/test/library-tests/types/exceptions/Reraises.ql +++ b/python/ql/test/library-tests/types/exceptions/Reraises.ql @@ -1,6 +1,4 @@ - import python from ReraisingNode r - -select r.getLocation().getStartLine(), r, r.getARaisedType().toString() \ No newline at end of file +select r.getLocation().getStartLine(), r, r.getARaisedType().toString() diff --git a/python/ql/test/library-tests/types/exceptions/Viable.ql b/python/ql/test/library-tests/types/exceptions/Viable.ql index 544b0a0d0b6..e28fa1a907c 100644 --- a/python/ql/test/library-tests/types/exceptions/Viable.ql +++ b/python/ql/test/library-tests/types/exceptions/Viable.ql @@ -1,7 +1,6 @@ - - import python from RaisingNode r, ControlFlowNode n, ClassObject ex where r.viableExceptionEdge(n, ex) -select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), n.getNode().toString(), ex.toString() +select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), + n.getNode().toString(), ex.toString() diff --git a/python/ql/test/library-tests/types/functions/Zope.ql b/python/ql/test/library-tests/types/functions/Zope.ql index 91b828b2ff2..ca1c1a0f596 100644 --- a/python/ql/test/library-tests/types/functions/Zope.ql +++ b/python/ql/test/library-tests/types/functions/Zope.ql @@ -1,4 +1,3 @@ - import python import semmle.python.libraries.Zope diff --git a/python/ql/test/library-tests/types/properties/Deleters.ql b/python/ql/test/library-tests/types/properties/Deleters.ql index e57f5917e6e..ad99ceb387d 100644 --- a/python/ql/test/library-tests/types/properties/Deleters.ql +++ b/python/ql/test/library-tests/types/properties/Deleters.ql @@ -1,5 +1,4 @@ import python from PythonPropertyObject p - select p.toString(), p.getDeleter().toString() diff --git a/python/ql/test/library-tests/types/properties/Getters.ql b/python/ql/test/library-tests/types/properties/Getters.ql index 2d495ccfc2f..5f232858696 100644 --- a/python/ql/test/library-tests/types/properties/Getters.ql +++ b/python/ql/test/library-tests/types/properties/Getters.ql @@ -1,5 +1,4 @@ import python from PythonPropertyObject p - select p.toString(), p.getGetter().toString() diff --git a/python/ql/test/library-tests/types/properties/PythonProperties.ql b/python/ql/test/library-tests/types/properties/PythonProperties.ql index 91281c321a0..858326d6ac0 100644 --- a/python/ql/test/library-tests/types/properties/PythonProperties.ql +++ b/python/ql/test/library-tests/types/properties/PythonProperties.ql @@ -1,5 +1,4 @@ import python -from PythonPropertyObject p - +from PythonPropertyObject p select p.toString() diff --git a/python/ql/test/library-tests/types/properties/Setters.ql b/python/ql/test/library-tests/types/properties/Setters.ql index 4e13e54db63..871e6f9145f 100644 --- a/python/ql/test/library-tests/types/properties/Setters.ql +++ b/python/ql/test/library-tests/types/properties/Setters.ql @@ -1,5 +1,4 @@ import python from PythonPropertyObject p - select p.toString(), p.getSetter().toString() diff --git a/python/ql/test/library-tests/variables/definitions/test.ql b/python/ql/test/library-tests/variables/definitions/test.ql index 9abee816b3a..a3f0fab8155 100644 --- a/python/ql/test/library-tests/variables/definitions/test.ql +++ b/python/ql/test/library-tests/variables/definitions/test.ql @@ -1,5 +1,4 @@ import python from DefinitionNode d - select d.getLocation().getStartLine(), d.getLocation().getStartColumn(), d.toString() diff --git a/python/ql/test/library-tests/variables/scopes/free.ql b/python/ql/test/library-tests/variables/scopes/free.ql index 1e15bb3a312..65789e76a52 100644 --- a/python/ql/test/library-tests/variables/scopes/free.ql +++ b/python/ql/test/library-tests/variables/scopes/free.ql @@ -1,7 +1,8 @@ import python from LocalVariable v, Scope inner -where v.escapes() and inner = v.getAnAccess().getScope() and -inner != v.getScope() +where + v.escapes() and + inner = v.getAnAccess().getScope() and + inner != v.getScope() select v.toString(), v.getScope().toString(), inner.toString() - diff --git a/python/ql/test/library-tests/variables/scopes/globals.ql b/python/ql/test/library-tests/variables/scopes/globals.ql index 8d200aa81b0..65e572c2ab4 100644 --- a/python/ql/test/library-tests/variables/scopes/globals.ql +++ b/python/ql/test/library-tests/variables/scopes/globals.ql @@ -2,4 +2,3 @@ import python from GlobalVariable l select l.toString(), l.getScope().toString() - diff --git a/python/ql/test/library-tests/variables/scopes/locals.ql b/python/ql/test/library-tests/variables/scopes/locals.ql index 264c5e9b7d1..62814925fe9 100644 --- a/python/ql/test/library-tests/variables/scopes/locals.ql +++ b/python/ql/test/library-tests/variables/scopes/locals.ql @@ -1,10 +1,8 @@ import python from LocalVariable l, string kind -where -l instanceof FastLocalVariable and kind = "fast" -or -l instanceof NameLocalVariable and kind = "name" - +where + l instanceof FastLocalVariable and kind = "fast" + or + l instanceof NameLocalVariable and kind = "name" select l, l.getScope(), kind - diff --git a/python/ql/test/library-tests/variables/scopes/lookup.ql b/python/ql/test/library-tests/variables/scopes/lookup.ql index c7a776c7caa..248cd62b911 100644 --- a/python/ql/test/library-tests/variables/scopes/lookup.ql +++ b/python/ql/test/library-tests/variables/scopes/lookup.ql @@ -2,15 +2,17 @@ import python from NameNode n, string l where -n.isLoad() and ( - n.isGlobal() and l = "global" - or - n.isLocal() and l = "local" - or - n.isNonLocal() and l = "non-local" - or - not n.isGlobal() and not n.isLocal() and - not n.isNonLocal() and - l = "none" -) + n.isLoad() and + ( + n.isGlobal() and l = "global" + or + n.isLocal() and l = "local" + or + n.isNonLocal() and l = "non-local" + or + not n.isGlobal() and + not n.isLocal() and + not n.isNonLocal() and + l = "none" + ) select n.getLocation().getStartLine(), n.toString(), l diff --git a/python/ql/test/library-tests/variables/scopes/scopes.ql b/python/ql/test/library-tests/variables/scopes/scopes.ql index b87a45c9939..b722b89e51e 100644 --- a/python/ql/test/library-tests/variables/scopes/scopes.ql +++ b/python/ql/test/library-tests/variables/scopes/scopes.ql @@ -1,4 +1,3 @@ - import python from Variable v, Scope s diff --git a/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql b/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql index cbeed6c2e4b..52fd7ff218e 100644 --- a/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql +++ b/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql @@ -1,11 +1,7 @@ import python - import semmle.python.web.Http import semmle.python.web.ClientHttpRequest from Client::HttpRequest req, string method -where - if exists(req.getMethodUpper()) - then method = req.getMethodUpper() - else method = "" +where if exists(req.getMethodUpper()) then method = req.getMethodUpper() else method = "" select req, req.getAUrlPart(), method diff --git a/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql b/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql index cbeed6c2e4b..52fd7ff218e 100644 --- a/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql +++ b/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql @@ -1,11 +1,7 @@ import python - import semmle.python.web.Http import semmle.python.web.ClientHttpRequest from Client::HttpRequest req, string method -where - if exists(req.getMethodUpper()) - then method = req.getMethodUpper() - else method = "" +where if exists(req.getMethodUpper()) then method = req.getMethodUpper() else method = "" select req, req.getAUrlPart(), method diff --git a/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql b/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql index cbeed6c2e4b..52fd7ff218e 100644 --- a/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql +++ b/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql @@ -1,11 +1,7 @@ import python - import semmle.python.web.Http import semmle.python.web.ClientHttpRequest from Client::HttpRequest req, string method -where - if exists(req.getMethodUpper()) - then method = req.getMethodUpper() - else method = "" +where if exists(req.getMethodUpper()) then method = req.getMethodUpper() else method = "" select req, req.getAUrlPart(), method diff --git a/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql b/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql index 545453e93eb..8525edcb8b8 100644 --- a/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql +++ b/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql @@ -1,7 +1,6 @@ - import python from Module m, ModuleMetrics mm where mm = m.getMetrics() and mm.getNumberOfLines() > 0 -select m, 100.0 * ((float)mm.getNumberOfLinesOfCode() / (float)mm.getNumberOfLines()) as ratio -order by ratio desc \ No newline at end of file +select m, 100.0 * (mm.getNumberOfLinesOfCode().(float) / mm.getNumberOfLines().(float)) as ratio + order by ratio desc diff --git a/python/ql/test/query-tests/Resources/Dataflow.ql b/python/ql/test/query-tests/Resources/Dataflow.ql index ee92ee981c3..4e2cf15b50d 100644 --- a/python/ql/test/query-tests/Resources/Dataflow.ql +++ b/python/ql/test/query-tests/Resources/Dataflow.ql @@ -1,16 +1,14 @@ - import python import Resources.FileOpen - from EssaVariable v, EssaDefinition def, string open, string exit -where def = v.getDefinition() and v.getSourceVariable().getName().charAt(0) = "f" and -( - var_is_open(v, _) and open = "open" - or - not var_is_open(v, _) and open = "closed" -) -and -if BaseFlow::reaches_exit(v) then exit = "exit" else exit = "" - +where + def = v.getDefinition() and + v.getSourceVariable().getName().charAt(0) = "f" and + ( + var_is_open(v, _) and open = "open" + or + not var_is_open(v, _) and open = "closed" + ) and + if BaseFlow::reaches_exit(v) then exit = "exit" else exit = "" select v.getRepresentation() + " = " + v.getDefinition().getRepresentation(), open, exit diff --git a/python/ql/test/query-tests/Security/CWE-327/TestNode.ql b/python/ql/test/query-tests/Security/CWE-327/TestNode.ql index 046378e4ea1..50305f21a2e 100644 --- a/python/ql/test/query-tests/Security/CWE-327/TestNode.ql +++ b/python/ql/test/query-tests/Security/CWE-327/TestNode.ql @@ -1,6 +1,5 @@ import python import semmle.python.security.TaintTracking - import python import semmle.python.security.SensitiveData import semmle.python.security.Crypto From a317b87b81f7995463862bcc071a4f37e9cea008 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 26 Mar 2020 16:13:59 +0000 Subject: [PATCH 186/459] JS: Fix perf issue in DictionaryTaintStep --- .../javascript/dataflow/TaintTracking.qll | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 2b70b6f9eca..91d8e880654 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -287,32 +287,32 @@ module TaintTracking { /** * A taint propagating data flow edge for assignments of the form `o[k] = v`, where * `k` is not a constant and `o` refers to some object literal; in this case, we consider - * taint to flow from `v` to any variable that refers to the object literal. + * taint to flow from `v` to that object literal. * * The rationale for this heuristic is that if properties of `o` are accessed by * computed (that is, non-constant) names, then `o` is most likely being treated as * a map, not as a real object. In this case, it makes sense to consider the entire * map to be tainted as soon as one of its entries is. */ - private class DictionaryTaintStep extends AdditionalTaintStep, DataFlow::ValueNode { - override VarAccess astNode; - DataFlow::Node source; - - DictionaryTaintStep() { - exists(AssignExpr assgn, IndexExpr idx, AbstractObjectLiteral obj | - assgn.getTarget() = idx and - idx.getBase().analyze().getAValue() = obj and - not exists(idx.getPropertyName()) and - astNode.analyze().getAValue() = obj and - source = DataFlow::valueNode(assgn.getRhs()) - ) - } + private class DictionaryTaintStep extends AdditionalTaintStep { + DictionaryTaintStep() { dictionaryTaintStep(_, this) } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { - pred = source and succ = this + succ = this and + dictionaryTaintStep(pred, succ) } } + /** Holds if there is a step `pred -> succ` used by `DictionaryTaintStep`. */ + private predicate dictionaryTaintStep(DataFlow::Node pred, DataFlow::ObjectLiteralNode succ) { + exists(AssignExpr assgn, IndexExpr idx | + assgn.getTarget() = idx and + succ.flowsToExpr(idx.getBase()) and + not exists(idx.getPropertyName()) and + pred = DataFlow::valueNode(assgn.getRhs()) + ) + } + /** * A taint propagating data flow edge for assignments of the form `c1.state.p = v`, * where `c1` is an instance of React component `C`; in this case, we consider From 727cde31c99dae7e9b1cd7b267a16644be5b1d96 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 30 Mar 2020 12:30:14 +0200 Subject: [PATCH 187/459] Python: Autoformat a few final stragglers. --- .../ql/src/semmle/python/dataflow/Implementation.qll | 9 ++++----- python/ql/src/semmle/python/web/django/General.qll | 11 ++--------- python/ql/src/semmle/python/web/django/Redirect.qll | 4 +--- python/ql/src/site.qll | 8 ++++---- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/Implementation.qll b/python/ql/src/semmle/python/dataflow/Implementation.qll index fdbc931d8f8..571a831b81f 100644 --- a/python/ql/src/semmle/python/dataflow/Implementation.qll +++ b/python/ql/src/semmle/python/dataflow/Implementation.qll @@ -963,11 +963,12 @@ private TaintKind taint_at_depth(SequenceKind parent_kind, int depth) { or // recursive case depth > 1 and - result = taint_at_depth(parent_kind.getMember(), depth-1) + result = taint_at_depth(parent_kind.getMember(), depth - 1) ) } -/** Helper predicate for taintedMultiAssignment +/** + * Helper predicate for taintedMultiAssignment * * Returns the `depth` the elements that are assigned to `left_defn` with iterable unpacking has, * compared to `left_parent`. Special care is taken for `StarredNode` that is assigned a sequence of items. @@ -982,9 +983,7 @@ int iterable_unpacking_descent(SequenceNode left_parent, ControlFlowNode left_de exists(Assign a | a.getATarget().getASubExpression*().getAFlowNode() = left_parent) and left_parent.getAnElement() = left_defn and // Handle `a, *b = some_iterable` - if left_defn instanceof StarredNode - then result = 0 - else result = 1 + if left_defn instanceof StarredNode then result = 0 else result = 1 or result = 1 + iterable_unpacking_descent(left_parent.getAnElement(), left_defn) } diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll index f2cc54f49b6..8d707a3a6e6 100644 --- a/python/ql/src/semmle/python/web/django/General.qll +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -27,11 +27,8 @@ abstract class DjangoRoute extends CallNode { * https://docs.djangoproject.com/en/3.0/topics/http/views/ */ class DjangoViewHandler extends PythonFunctionValue { - /** Gets the index of the 'request' argument */ - int getRequestArgIndex() { - result = 0 - } + int getRequestArgIndex() { result = 0 } } /** @@ -48,11 +45,7 @@ private class DjangoViewClass extends ClassValue { } class DjangoClassBasedViewHandler extends DjangoViewHandler { - DjangoClassBasedViewHandler() { - exists(DjangoViewClass cls | - cls.lookup(httpVerbLower()) = this - ) - } + DjangoClassBasedViewHandler() { exists(DjangoViewClass cls | cls.lookup(httpVerbLower()) = this) } override int getRequestArgIndex() { // due to `self` being the first parameter diff --git a/python/ql/src/semmle/python/web/django/Redirect.qll b/python/ql/src/semmle/python/web/django/Redirect.qll index cc63f678973..a550088eaf6 100644 --- a/python/ql/src/semmle/python/web/django/Redirect.qll +++ b/python/ql/src/semmle/python/web/django/Redirect.qll @@ -16,7 +16,5 @@ private import semmle.python.web.Http class DjangoRedirect extends HttpRedirectTaintSink { override string toString() { result = "django.redirect" } - DjangoRedirect() { - this = redirect().getACall().getAnArg() - } + DjangoRedirect() { this = redirect().getACall().getAnArg() } } diff --git a/python/ql/src/site.qll b/python/ql/src/site.qll index 3a301497828..a09d9ad8a76 100644 --- a/python/ql/src/site.qll +++ b/python/ql/src/site.qll @@ -1,7 +1,7 @@ -/** Site library - * + +/* + * Site library + * * Include predicates and classes here, if they are required to customize all analysis. - * */ - From ab4cef53c29eb39bf801d99819bff6e6d400b4f4 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 30 Mar 2020 12:36:43 +0200 Subject: [PATCH 188/459] Python: Autoformat one final straggler. --- python/ql/src/Security/CWE-078/CommandInjection.ql | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/ql/src/Security/CWE-078/CommandInjection.ql b/python/ql/src/Security/CWE-078/CommandInjection.ql index f263f92bea2..aec3cb63b25 100755 --- a/python/ql/src/Security/CWE-078/CommandInjection.ql +++ b/python/ql/src/Security/CWE-078/CommandInjection.ql @@ -28,9 +28,7 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration { source instanceof HttpRequestTaintSource } - override predicate isSink(TaintTracking::Sink sink) { - sink instanceof CommandSink - } + override predicate isSink(TaintTracking::Sink sink) { sink instanceof CommandSink } override predicate isExtension(TaintTracking::Extension extension) { extension instanceof FirstElementFlow From 2229e34466790d25579cbb5aae593d089452ce2e Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 30 Mar 2020 13:14:37 +0200 Subject: [PATCH 189/459] Python: Fix outdated link in `ImportFailure.qhelp`. --- python/ql/src/analysis/ImportFailure.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/analysis/ImportFailure.qhelp b/python/ql/src/analysis/ImportFailure.qhelp index 2832f217f3b..b8ae9ee2c0c 100644 --- a/python/ql/src/analysis/ImportFailure.qhelp +++ b/python/ql/src/analysis/ImportFailure.qhelp @@ -21,7 +21,7 @@ Ensure that all required modules and packages can be found when running the extr -
  • Semmle Tutorial: Basic project creation (Python).
  • +
  • Semmle Tutorial: Creating a CodeQL database.
  • From b990fac97bc691c056bc2407ad21dc1b77cd8e24 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 30 Mar 2020 13:55:38 +0200 Subject: [PATCH 190/459] Python: Fix test failures. How could the tests fail because of autoformatting, you may ask? The answer is deprecation warnings. These specify the location of the deprecated entity, and due to autoformatting these moved around. --- .../PointsTo/consts/BooleanConstants.expected | 4 ++-- .../library-tests/PointsTo/customise/test.expected | 2 +- .../library-tests/PointsTo/extensions/Extend.expected | 10 +++++----- .../PointsTo/new/PointsToWithContext.expected | 2 +- .../PointsTo/new/PointsToWithType.expected | 2 +- python/ql/test/library-tests/PointsTo/new/SSA.expected | 2 +- .../taint/exception_traceback/TestNode.expected | 2 +- .../library-tests/taint/extensions/TestNode.expected | 2 +- .../library-tests/taint/extensions/TestStep.expected | 4 ++-- .../test/library-tests/taint/general/Contexts.expected | 4 ++-- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected index 3395885a548..4c45f134a93 100644 --- a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected +++ b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected @@ -1,5 +1,5 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:8,5-24) -WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:11,5-24) +WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:6,25-44) +WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:7,29-48) | module.py | 2 | ControlFlowNode for ImportExpr | import | true | | module.py | 2 | ControlFlowNode for sys | import | true | | module.py | 3 | ControlFlowNode for Compare | import | false | diff --git a/python/ql/test/library-tests/PointsTo/customise/test.expected b/python/ql/test/library-tests/PointsTo/customise/test.expected index 93c49242708..009572ad1c5 100644 --- a/python/ql/test/library-tests/PointsTo/customise/test.expected +++ b/python/ql/test/library-tests/PointsTo/customise/test.expected @@ -1,4 +1,4 @@ -WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (test.ql:8,27-51) +WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (test.ql:9,27-51) | 9 | ControlFlowNode for has_type_int | Function has_type_int | builtin-class function | | 9 | ControlFlowNode for has_type_int() | has_type_int() | builtin-class int | | 9 | ControlFlowNode for x | has_type_int() | builtin-class int | diff --git a/python/ql/test/library-tests/PointsTo/extensions/Extend.expected b/python/ql/test/library-tests/PointsTo/extensions/Extend.expected index 791f854e105..0220ccb12ec 100644 --- a/python/ql/test/library-tests/PointsTo/extensions/Extend.expected +++ b/python/ql/test/library-tests/PointsTo/extensions/Extend.expected @@ -1,8 +1,8 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (Extend.ql:58,9-28) -WARNING: Type CustomPointsToAttribute has been deprecated and may be removed in future (Extend.ql:27,35-58) -WARNING: Type CustomPointsToObjectFact has been deprecated and may be removed in future (Extend.ql:42,32-56) -WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:9,28-52) -WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:55,38-62) +WARNING: Predicate points_to has been deprecated and may be removed in future (Extend.ql:50,32-51) +WARNING: Type CustomPointsToAttribute has been deprecated and may be removed in future (Extend.ql:22,34-57) +WARNING: Type CustomPointsToObjectFact has been deprecated and may be removed in future (Extend.ql:38,32-56) +WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:5,28-52) +WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:49,38-62) | test.py:4:1:4:3 | ControlFlowNode for one | int 1 | | test.py:5:1:5:3 | ControlFlowNode for two | int 2 | | test.py:8:1:8:1 | ControlFlowNode for IntegerLiteral | int 1 | diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected index c3a1eebc413..5b452c39073 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected @@ -1,4 +1,4 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithContext.ql:8,7-26) +WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithContext.ql:7,7-26) | a_simple.py:2 | ControlFlowNode for FloatLiteral | float 1.0 | builtin-class float | 2 | import | | a_simple.py:2 | ControlFlowNode for f1 | float 1.0 | builtin-class float | 2 | import | | a_simple.py:3 | ControlFlowNode for dict | builtin-class dict | builtin-class type | 3 | import | diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected index 84bf64aacfa..21c14f75a4e 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected @@ -1,4 +1,4 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithType.ql:7,7-26) +WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithType.ql:6,7-26) | a_simple.py:2 | ControlFlowNode for FloatLiteral | float 1.0 | builtin-class float | 2 | | a_simple.py:2 | ControlFlowNode for f1 | float 1.0 | builtin-class float | 2 | | a_simple.py:3 | ControlFlowNode for dict | builtin-class dict | builtin-class type | 3 | diff --git a/python/ql/test/library-tests/PointsTo/new/SSA.expected b/python/ql/test/library-tests/PointsTo/new/SSA.expected index d4858045a9f..fb0b2156ecc 100644 --- a/python/ql/test/library-tests/PointsTo/new/SSA.expected +++ b/python/ql/test/library-tests/PointsTo/new/SSA.expected @@ -1,4 +1,4 @@ -WARNING: Predicate ssa_variable_points_to has been deprecated and may be removed in future (SSA.ql:10,1-33) +WARNING: Predicate ssa_variable_points_to has been deprecated and may be removed in future (SSA.ql:10,5-37) | __init__.py:0 | __name___0 = ScopeEntryDefinition | 'code' | builtin-class str | | __init__.py:0 | __name___0 = ScopeEntryDefinition | 'code.package' | builtin-class str | | __init__.py:0 | __name___0 = ScopeEntryDefinition | 'code.test_package' | builtin-class str | diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected b/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected index 98b1ceba4e4..4ee4e15cefd 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected +++ b/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected @@ -1,4 +1,4 @@ -WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:8,43-50) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:7,43-50) | test.py:10:11:10:47 | test.py:10 | MyException() | exception.kind | | test.py:15:25:15:25 | test.py:15 | e | exception.kind | | test.py:16:13:16:34 | test.py:16 | Attribute() | exception.info | diff --git a/python/ql/test/library-tests/taint/extensions/TestNode.expected b/python/ql/test/library-tests/taint/extensions/TestNode.expected index 71a89d1792c..ac67500eb3e 100644 --- a/python/ql/test/library-tests/taint/extensions/TestNode.expected +++ b/python/ql/test/library-tests/taint/extensions/TestNode.expected @@ -1,4 +1,4 @@ -WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:7,77-84) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:5,77-84) | Taint simple.test | visitor.py:10 | arg | p2 = simple.test | | Taint simple.test | visitor.py:13 | arg | p2 = simple.test | | Taint simple.test | visitor.py:18 | arg | | diff --git a/python/ql/test/library-tests/taint/extensions/TestStep.expected b/python/ql/test/library-tests/taint/extensions/TestStep.expected index da27b3caf9e..c5915950d98 100644 --- a/python/ql/test/library-tests/taint/extensions/TestStep.expected +++ b/python/ql/test/library-tests/taint/extensions/TestStep.expected @@ -1,5 +1,5 @@ -WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:9,74-81) -WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:11,74-81) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:6,77-84) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:8,17-24) | Taint simple.test | visitor.py:10 | arg | p2 = simple.test | --> | Taint simple.test | visitor.py:13 | arg | p2 = simple.test | | Taint simple.test | visitor.py:18 | arg | | --> | Taint simple.test | visitor.py:19 | arg | | | Taint simple.test | visitor.py:19 | arg | | --> | Taint simple.test | visitor.py:26 | Attribute() | | diff --git a/python/ql/test/library-tests/taint/general/Contexts.expected b/python/ql/test/library-tests/taint/general/Contexts.expected index f07c1452c6e..cfce11fbaa9 100644 --- a/python/ql/test/library-tests/taint/general/Contexts.expected +++ b/python/ql/test/library-tests/taint/general/Contexts.expected @@ -1,5 +1,5 @@ -WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:6,6-17) -WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:7,14-25) +WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:5,6-17) +WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:7,12-23) | assignment.py:1 | p0 = simple.test | Function test | | assignment.py:1 | p1 = simple.test | Function test | | assignment.py:1 | p2 = simple.test | Function test | From 365751412cedb7da798d67fc80474e727774cd63 Mon Sep 17 00:00:00 2001 From: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> Date: Mon, 30 Mar 2020 14:24:22 +0100 Subject: [PATCH 191/459] Docs: Bump supported Go version. cf https://github.com/github/codeql-go/pull/39 --- docs/language/support/versions-compilers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/support/versions-compilers.csv b/docs/language/support/versions-compilers.csv index 343de95dfba..8b60f8ee3a9 100644 --- a/docs/language/support/versions-compilers.csv +++ b/docs/language/support/versions-compilers.csv @@ -9,7 +9,7 @@ Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019, .NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" -Go (aka Golang), "Go up to 1.13", "Go 1.11 or more recent", ``.go`` +Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go`` Java,"Java 6 to 13 [4]_","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [5]_",``.java`` From dd322be23809d60935c85dec9ba717e09a5eaa83 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 30 Mar 2020 15:49:24 +0200 Subject: [PATCH 192/459] C++: Remove noise from argHasPostUpdate check This consistency check seems to have value for AST data flow, but I've disabled it on the IR for now. This commit also includes two unrelated changes that seem to fix a semantic merge conflict. --- .../cpp/dataflow/internal/DataFlowPrivate.qll | 17 +- .../ir/dataflow/internal/DataFlowPrivate.qll | 6 +- .../dataflow-consistency.expected | 230 ------------- .../dataflow-ir-consistency.expected | 322 +----------------- 4 files changed, 23 insertions(+), 552 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 514bfd6261d..1c6ab9a8c46 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -301,4 +301,19 @@ int accessPathLimit() { result = 5 } * * This predicate is only used for consistency checks. */ -predicate isImmutableOrUnobservable(Node n) { none() } +predicate isImmutableOrUnobservable(Node n) { + // Is the null pointer (or something that's not really a pointer) + exists(n.asExpr().getValue()) + or + // Isn't a pointer or is a pointer to const + forall(DerivedType dt | dt = n.asExpr().getActualType() | + dt.getBaseType().isConst() + or + dt.getBaseType() instanceof RoutineType + ) + or + // Isn't something we can track + n.asExpr() instanceof Call + // The above list of cases isn't exhaustive, but it narrows down the + // consistency alerts enough that most of them are interesting. +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index bb76bc6370c..6db341c2cbc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -210,4 +210,8 @@ int accessPathLimit() { result = 5 } * * This predicate is only used for consistency checks. */ -predicate isImmutableOrUnobservable(Node n) { none() } +predicate isImmutableOrUnobservable(Node n) { + // The rules for whether an IR argument gets a post-update node are too + // complex to model here. + any() +} diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected index f024791bf06..10dc6d411b7 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -23,239 +23,9 @@ postIsInSameCallable reverseRead storeIsPostUpdate argHasPostUpdate -| BarrierGuard.cpp:6:15:6:20 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:7:10:7:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:9:10:9:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:14:16:14:21 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:15:10:15:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:17:10:17:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:22:15:22:20 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:23:10:23:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:25:10:25:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:30:15:30:20 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:31:10:31:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:33:10:33:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:38:16:38:21 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:41:8:41:13 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:50:18:50:18 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:51:13:51:13 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:52:25:52:25 | y | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:53:13:53:13 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:54:25:54:25 | y | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:55:13:55:13 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:61:19:61:19 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:62:14:62:14 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:63:26:63:26 | y | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:64:14:64:14 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:65:26:65:26 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:66:14:66:14 | x | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:12:8:12:8 | x | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:19:27:19:32 | call to source | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:28:8:28:8 | x | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:34:8:34:8 | x | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:41:19:41:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:18:8:18:19 | sourceArray1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:20:8:20:22 | access to array | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:21:8:21:20 | * ... | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:24:22:24:23 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:25:27:25:28 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:26:27:26:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:29:27:29:28 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:30:27:30:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:31:27:31:28 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:32:22:32:23 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:37:10:37:11 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:41:18:41:19 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:45:17:45:18 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:47:8:47:30 | call to expression | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:51:8:51:17 | stackArray | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:11:38:11:38 | x | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:23:38:23:38 | x | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:31:16:31:24 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:32:16:32:24 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:33:18:33:23 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:35:16:35:25 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:36:16:36:25 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:37:19:37:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:39:15:39:23 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:40:15:40:23 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:41:17:41:22 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:43:15:43:24 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:44:15:44:24 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:45:18:45:23 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:55:22:55:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:56:22:56:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:58:28:58:36 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:69:15:69:20 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:73:14:73:19 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:77:21:77:34 | call to allocateBottom | ArgumentNode is missing PostUpdateNode. | | dispatch.cpp:78:23:78:39 | * ... | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:81:13:81:18 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:89:28:89:33 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:90:25:90:30 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:96:8:96:8 | x | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:107:17:107:22 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:108:16:108:21 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:129:18:129:25 | call to isSource | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:130:17:130:24 | call to isSource | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:140:8:140:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:144:8:144:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:153:37:153:37 | f | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:154:37:154:37 | g | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:160:8:160:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:164:8:164:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:173:42:173:42 | f | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:174:42:174:42 | g | ArgumentNode is missing PostUpdateNode. | -| globals.cpp:6:10:6:14 | local | ArgumentNode is missing PostUpdateNode. | -| globals.cpp:12:10:12:24 | flowTestGlobal1 | ArgumentNode is missing PostUpdateNode. | -| globals.cpp:19:10:19:24 | flowTestGlobal2 | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:14:3:14:6 | t | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:15:3:15:6 | u | ArgumentNode is missing PostUpdateNode. | | lambdas.cpp:18:7:18:7 | a | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:18:8:18:8 | call to operator() | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:21:3:21:6 | t | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:22:3:22:6 | u | ArgumentNode is missing PostUpdateNode. | | lambdas.cpp:25:2:25:2 | b | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:26:7:26:7 | v | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:29:3:29:6 | t | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:30:3:30:6 | u | ArgumentNode is missing PostUpdateNode. | | lambdas.cpp:32:2:32:2 | c | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:35:8:35:8 | a | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:36:8:36:8 | b | ArgumentNode is missing PostUpdateNode. | | lambdas.cpp:38:2:38:2 | d | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:38:4:38:4 | t | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:38:7:38:7 | u | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:41:8:41:8 | a | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:42:8:42:8 | b | ArgumentNode is missing PostUpdateNode. | | lambdas.cpp:45:2:45:2 | e | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:46:7:46:7 | w | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:16:12:16:14 | lhs | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:16:17:16:19 | rhs | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:16:17:16:19 | rhs | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:55:23:55:28 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:56:10:56:11 | x1 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:58:19:58:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:59:10:59:11 | x2 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:62:10:62:11 | x3 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:65:10:65:11 | x4 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:79:17:79:19 | rhs | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:122:23:122:28 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:123:13:123:15 | val | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:125:19:125:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:126:13:126:15 | val | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:129:13:129:15 | val | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:132:13:132:15 | val | ArgumentNode is missing PostUpdateNode. | -| test.cpp:7:8:7:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:9:8:9:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:10:8:10:9 | t2 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:13:10:13:11 | t2 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:15:8:15:9 | t2 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:21:8:21:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:26:8:26:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:30:8:30:8 | t | ArgumentNode is missing PostUpdateNode. | -| test.cpp:31:8:31:8 | c | ArgumentNode is missing PostUpdateNode. | -| test.cpp:35:10:35:15 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:35:20:35:20 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:36:10:36:10 | 1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:36:13:36:18 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:43:10:43:20 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:46:10:46:10 | t | ArgumentNode is missing PostUpdateNode. | -| test.cpp:58:10:58:10 | t | ArgumentNode is missing PostUpdateNode. | -| test.cpp:71:8:71:9 | x4 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:76:8:76:9 | u1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:78:8:78:9 | u1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:81:8:81:9 | i1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:84:8:84:18 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:86:8:86:9 | i1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:90:8:90:14 | source1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:92:8:92:14 | source1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:103:10:103:12 | ref | ArgumentNode is missing PostUpdateNode. | -| test.cpp:110:10:110:12 | ref | ArgumentNode is missing PostUpdateNode. | -| test.cpp:138:27:138:32 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:140:8:140:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:144:8:144:8 | s | ArgumentNode is missing PostUpdateNode. | -| test.cpp:149:33:149:33 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:150:8:150:8 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:151:33:151:38 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:152:8:152:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:157:8:157:8 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:162:34:162:34 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:163:8:163:8 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:164:34:164:39 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:165:8:165:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:178:8:178:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:194:29:194:34 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:197:10:197:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:202:10:202:16 | barrier | ArgumentNode is missing PostUpdateNode. | -| test.cpp:207:35:207:35 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:208:10:208:10 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:209:35:209:40 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:210:10:210:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:216:10:216:10 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:221:36:221:36 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:222:10:222:10 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:223:36:223:41 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:224:10:224:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:238:10:238:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:245:14:245:19 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:246:18:246:23 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:251:14:251:14 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:256:14:256:20 | barrier | ArgumentNode is missing PostUpdateNode. | -| test.cpp:260:12:260:12 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:265:22:265:27 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:266:12:266:12 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:267:22:267:27 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:268:12:268:12 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:273:21:273:21 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:278:21:278:27 | barrier | ArgumentNode is missing PostUpdateNode. | -| test.cpp:289:14:289:14 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:291:14:291:14 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:314:4:314:9 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:317:12:317:12 | p | ArgumentNode is missing PostUpdateNode. | -| test.cpp:318:7:318:7 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:319:12:319:12 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:320:7:320:7 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:337:10:337:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:339:10:339:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:343:10:343:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:349:10:349:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:363:10:363:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:365:10:365:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:369:10:369:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:375:10:375:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:384:16:384:23 | & ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:384:26:384:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:385:8:385:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:391:16:391:23 | & ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:391:26:391:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:392:8:392:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:394:10:394:12 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:400:16:400:22 | & ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:400:25:400:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:401:8:401:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:407:16:407:22 | & ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:407:25:407:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:408:8:408:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:418:8:418:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:424:8:424:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:430:8:430:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:431:8:431:13 | * ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:436:26:436:26 | 1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:437:8:437:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:442:25:442:25 | 2 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:443:8:443:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:444:8:444:13 | * ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:450:9:450:22 | (statement expression) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:451:9:451:21 | (statement expression) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:461:8:461:12 | local | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:13:8:13:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:21:8:21:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:29:8:29:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:39:8:39:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:49:8:49:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:57:8:57:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:66:8:66:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:78:8:78:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:86:8:86:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:93:8:93:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:105:8:105:8 | x | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index 6b847acb3e8..7abb7b4f4ae 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -19,7 +19,9 @@ uniqueNodeLocation missingLocation | Nodes without location: 4 | uniqueNodeToString +| lambdas.cpp:2:6:2:9 | (no string representation) | Node should have one toString but has 0. | missingToString +| Nodes without toString: 1 | parameterCallable localFlowIsLocal compatibleTypesReflexive @@ -32,323 +34,3 @@ postIsInSameCallable reverseRead storeIsPostUpdate argHasPostUpdate -| BarrierGuard.cpp:6:15:6:20 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:7:10:7:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:9:10:9:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:14:16:14:21 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:15:10:15:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:17:10:17:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:22:15:22:20 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:23:10:23:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:25:10:25:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:30:15:30:20 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:31:10:31:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:33:10:33:15 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:38:16:38:21 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:41:8:41:13 | source | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:50:18:50:18 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:51:13:51:13 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:52:25:52:25 | y | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:53:13:53:13 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:54:25:54:25 | y | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:55:13:55:13 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:61:19:61:19 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:62:14:62:14 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:63:26:63:26 | y | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:64:14:64:14 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:65:26:65:26 | x | ArgumentNode is missing PostUpdateNode. | -| BarrierGuard.cpp:66:14:66:14 | x | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:12:8:12:8 | (int)... | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:19:27:19:32 | call to source | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:28:8:28:8 | (int)... | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:34:8:34:8 | (int)... | ArgumentNode is missing PostUpdateNode. | -| acrossLinkTargets.cpp:41:19:41:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:18:8:18:19 | (const int *)... | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:20:8:20:22 | access to array | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:21:8:21:20 | * ... | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:22:8:22:20 | & ... | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:24:22:24:23 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:25:27:25:28 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:26:8:26:24 | sourceStruct1_ptr | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:26:27:26:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:29:27:29:28 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:30:8:30:24 | sourceStruct1_ptr | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:30:27:30:34 | call to getFirst | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:31:27:31:28 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:32:22:32:23 | m1 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:37:10:37:11 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:41:18:41:19 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:45:17:45:18 | m2 | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:47:8:47:30 | call to expression | ArgumentNode is missing PostUpdateNode. | -| clang.cpp:51:8:51:17 | (const int *)... | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:11:38:11:38 | x | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:15:8:15:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:21:8:21:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:23:38:23:38 | x | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:31:8:31:13 | topPtr | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:31:16:31:24 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:32:8:32:13 | topPtr | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:32:16:32:24 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:33:3:33:8 | topPtr | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:33:18:33:23 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:35:8:35:13 | topPtr | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:35:16:35:25 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:36:8:36:13 | topPtr | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:36:16:36:25 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:37:3:37:8 | topPtr | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:37:19:37:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:39:8:39:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:39:15:39:23 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:40:8:40:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:40:15:40:23 | call to isSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:41:3:41:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:41:17:41:22 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:43:8:43:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:43:15:43:24 | call to notSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:44:8:44:13 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:44:15:44:24 | call to notSource2 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:45:3:45:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:45:18:45:23 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:55:8:55:19 | globalBottom | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:55:22:55:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:56:8:56:19 | globalMiddle | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:56:22:56:30 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:58:8:58:23 | call to readGlobalBottom | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:58:28:58:36 | call to isSource1 | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:60:18:60:29 | Constant | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:60:18:60:29 | new | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:61:18:61:29 | Constant | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:61:18:61:29 | new | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:65:10:65:21 | Constant | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:65:10:65:21 | new | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:69:3:69:5 | top | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:69:15:69:20 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:73:3:73:5 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:73:14:73:19 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:77:21:77:34 | call to allocateBottom | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:78:23:78:39 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:81:3:81:3 | x | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:81:13:81:18 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:89:3:89:10 | call to identity | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:89:12:89:17 | (Top *)... | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:89:28:89:33 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:90:3:90:10 | call to identity | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:90:12:90:14 | top | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:90:25:90:30 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:96:8:96:8 | x | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:107:17:107:22 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:108:16:108:21 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:129:10:129:15 | topPtr | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:129:18:129:25 | call to isSource | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:130:10:130:15 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:130:17:130:24 | call to isSource | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:140:8:140:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:144:8:144:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:153:37:153:37 | f | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:154:37:154:37 | g | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:160:8:160:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:164:8:164:13 | call to source | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:173:42:173:42 | f | ArgumentNode is missing PostUpdateNode. | -| dispatch.cpp:174:42:174:42 | g | ArgumentNode is missing PostUpdateNode. | -| example.c:26:18:26:24 | & ... | ArgumentNode is missing PostUpdateNode. | -| example.c:28:14:28:25 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | t | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | t | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | u | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | u | ArgumentNode is missing PostUpdateNode. | -| globals.cpp:6:10:6:14 | local | ArgumentNode is missing PostUpdateNode. | -| globals.cpp:12:10:12:24 | flowTestGlobal1 | ArgumentNode is missing PostUpdateNode. | -| globals.cpp:19:10:19:24 | flowTestGlobal2 | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:18:7:18:7 | (const lambda [] type at line 13, col. 11)... | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:18:8:18:8 | call to operator() | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:21:8:21:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:22:8:22:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:25:2:25:2 | (const lambda [] type at line 20, col. 11)... | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:26:7:26:7 | v | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:32:2:32:2 | (const lambda [] type at line 28, col. 11)... | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:35:8:35:8 | a | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:36:8:36:8 | b | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:38:2:38:2 | (const lambda [] type at line 34, col. 11)... | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:38:4:38:4 | t | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:38:7:38:7 | u | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:41:8:41:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:42:8:42:8 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:45:2:45:2 | (const lambda [] type at line 40, col. 11)... | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:45:4:45:4 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:45:7:45:7 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:45:10:45:10 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| lambdas.cpp:46:7:46:7 | w | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:16:12:16:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:16:17:16:19 | rhs | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:37:21:37:23 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:55:19:55:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:55:23:55:28 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:56:10:56:11 | x1 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:58:15:58:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:58:19:58:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:59:10:59:11 | x2 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:61:26:61:27 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:62:10:62:11 | x3 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:64:15:64:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:65:10:65:11 | x4 | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:79:12:79:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:79:17:79:19 | rhs | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:102:21:102:23 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:122:19:122:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:122:23:122:28 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:123:13:123:15 | val | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:125:15:125:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:125:19:125:24 | call to source | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:126:13:126:15 | val | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:128:26:128:27 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:129:13:129:15 | val | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:131:15:131:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ref.cpp:132:13:132:15 | val | ArgumentNode is missing PostUpdateNode. | -| test.cpp:7:8:7:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:9:8:9:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:10:8:10:9 | t2 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:13:10:13:11 | t2 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:15:8:15:9 | t2 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:21:8:21:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:26:8:26:9 | t1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:30:8:30:8 | t | ArgumentNode is missing PostUpdateNode. | -| test.cpp:31:8:31:8 | c | ArgumentNode is missing PostUpdateNode. | -| test.cpp:35:10:35:15 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:35:20:35:20 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:36:10:36:10 | 1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:36:13:36:18 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:43:10:43:20 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:46:10:46:10 | t | ArgumentNode is missing PostUpdateNode. | -| test.cpp:58:10:58:10 | t | ArgumentNode is missing PostUpdateNode. | -| test.cpp:67:29:67:35 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:71:8:71:9 | x4 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:76:8:76:9 | u1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:78:8:78:9 | u1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:81:8:81:9 | i1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:84:8:84:18 | ... ? ... : ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:86:8:86:9 | i1 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:90:8:90:14 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:92:8:92:14 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:103:10:103:12 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:110:10:110:12 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:138:27:138:32 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:140:8:140:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:144:8:144:8 | s | ArgumentNode is missing PostUpdateNode. | -| test.cpp:149:33:149:33 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:150:8:150:8 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:151:33:151:38 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:152:8:152:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:157:8:157:8 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:162:34:162:34 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:163:8:163:8 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:164:34:164:39 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:165:8:165:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:178:8:178:8 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:194:29:194:34 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:197:10:197:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:202:10:202:16 | barrier | ArgumentNode is missing PostUpdateNode. | -| test.cpp:207:35:207:35 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:208:10:208:10 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:209:35:209:40 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:210:10:210:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:216:10:216:10 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:221:36:221:36 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:222:10:222:10 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:223:36:223:41 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:224:10:224:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:238:10:238:10 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:245:14:245:19 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:246:18:246:23 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:251:14:251:14 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:256:14:256:20 | barrier | ArgumentNode is missing PostUpdateNode. | -| test.cpp:260:12:260:12 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:265:22:265:27 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:266:12:266:12 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:267:22:267:27 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:268:12:268:12 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:273:21:273:21 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:278:21:278:27 | barrier | ArgumentNode is missing PostUpdateNode. | -| test.cpp:289:14:289:14 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:291:14:291:14 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:314:4:314:9 | call to source | ArgumentNode is missing PostUpdateNode. | -| test.cpp:317:12:317:12 | p | ArgumentNode is missing PostUpdateNode. | -| test.cpp:318:7:318:7 | x | ArgumentNode is missing PostUpdateNode. | -| test.cpp:319:12:319:12 | 0 | ArgumentNode is missing PostUpdateNode. | -| test.cpp:320:7:320:7 | y | ArgumentNode is missing PostUpdateNode. | -| test.cpp:337:10:337:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:339:10:339:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:343:10:343:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:349:10:349:18 | globalVar | ArgumentNode is missing PostUpdateNode. | -| test.cpp:363:10:363:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:365:10:365:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:369:10:369:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:375:10:375:14 | field | ArgumentNode is missing PostUpdateNode. | -| test.cpp:384:10:384:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:384:16:384:23 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:384:26:384:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:385:8:385:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:391:10:391:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:391:16:391:23 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:391:26:391:35 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:392:8:392:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:394:10:394:12 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:400:10:400:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:400:16:400:22 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:400:25:400:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:401:8:401:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:407:10:407:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:407:16:407:22 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:407:25:407:34 | sizeof() | ArgumentNode is missing PostUpdateNode. | -| test.cpp:408:8:408:10 | tmp | ArgumentNode is missing PostUpdateNode. | -| test.cpp:417:16:417:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:418:8:418:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:423:20:423:25 | & ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:424:8:424:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:429:20:429:24 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| test.cpp:430:8:430:12 | (const int *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:431:8:431:13 | * ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:436:18:436:23 | & ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:436:26:436:26 | (size_t)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:437:8:437:12 | local | ArgumentNode is missing PostUpdateNode. | -| test.cpp:442:18:442:22 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| test.cpp:442:25:442:25 | (size_t)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:443:8:443:12 | (const int *)... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:444:8:444:13 | * ... | ArgumentNode is missing PostUpdateNode. | -| test.cpp:450:9:450:22 | (statement expression) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:451:9:451:21 | (statement expression) | ArgumentNode is missing PostUpdateNode. | -| test.cpp:461:8:461:12 | local | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:13:8:13:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:21:8:21:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:29:8:29:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:39:8:39:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:49:8:49:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:57:8:57:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:66:8:66:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:78:8:78:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:86:8:86:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:93:8:93:8 | x | ArgumentNode is missing PostUpdateNode. | -| true_upon_entry.cpp:105:8:105:8 | x | ArgumentNode is missing PostUpdateNode. | From 531ef64c5dc6324681cafe432e217c883be4f65c Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 30 Mar 2020 17:45:53 +0200 Subject: [PATCH 193/459] C++: Fix other copies of the argHasPostUpdate test --- .../fields/dataflow-consistency.expected | 76 ----- .../fields/dataflow-ir-consistency.expected | 312 ------------------ .../syntax-zoo/dataflow-consistency.expected | 188 ----------- .../dataflow-ir-consistency.expected | 310 +---------------- 4 files changed, 3 insertions(+), 883 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected index 137400639a8..cdf03b90508 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -41,94 +41,18 @@ postIsInSameCallable reverseRead storeIsPostUpdate argHasPostUpdate -| A.cpp:40:15:40:21 | 0 | ArgumentNode is missing PostUpdateNode. | | A.cpp:41:15:41:21 | new | ArgumentNode is missing PostUpdateNode. | | A.cpp:55:12:55:19 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:56:13:56:15 | call to get | ArgumentNode is missing PostUpdateNode. | | A.cpp:57:17:57:23 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:57:28:57:30 | call to get | ArgumentNode is missing PostUpdateNode. | | A.cpp:64:21:64:28 | new | ArgumentNode is missing PostUpdateNode. | | A.cpp:73:25:73:32 | new | ArgumentNode is missing PostUpdateNode. | | A.cpp:126:12:126:18 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:151:21:151:21 | call to r | ArgumentNode is missing PostUpdateNode. | | A.cpp:160:32:160:59 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:43:160:49 | 0 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:52:160:58 | 0 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:161:29:161:35 | 0 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:162:29:162:35 | 0 | ArgumentNode is missing PostUpdateNode. | -| B.cpp:7:28:7:34 | 0 | ArgumentNode is missing PostUpdateNode. | -| B.cpp:16:28:16:34 | 0 | ArgumentNode is missing PostUpdateNode. | -| C.cpp:29:10:29:11 | s1 | ArgumentNode is missing PostUpdateNode. | -| C.cpp:30:10:30:11 | s2 | ArgumentNode is missing PostUpdateNode. | -| C.cpp:31:10:31:11 | s3 | ArgumentNode is missing PostUpdateNode. | -| C.cpp:32:10:32:11 | s4 | ArgumentNode is missing PostUpdateNode. | -| D.cpp:22:25:22:31 | call to getElem | ArgumentNode is missing PostUpdateNode. | | D.cpp:29:24:29:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:29:33:29:39 | 0 | ArgumentNode is missing PostUpdateNode. | | D.cpp:36:24:36:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:36:33:36:39 | 0 | ArgumentNode is missing PostUpdateNode. | | D.cpp:43:24:43:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:43:33:43:39 | 0 | ArgumentNode is missing PostUpdateNode. | | D.cpp:50:24:50:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:50:33:50:39 | 0 | ArgumentNode is missing PostUpdateNode. | | D.cpp:57:25:57:41 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:57:34:57:40 | 0 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:27:14:27:15 | s3 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:29:11:29:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:30:11:30:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:31:11:31:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:38:11:38:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:43:13:43:14 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:50:11:50:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:55:14:55:15 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:62:14:62:15 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:73:12:73:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:80:12:80:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:87:12:87:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:93:12:93:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:40:12:40:15 | this | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:44:26:44:29 | this | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:50:17:50:26 | call to user_input | ArgumentNode is missing PostUpdateNode. | | by_reference.cpp:51:8:51:8 | s | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:51:10:51:20 | call to getDirectly | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:56:19:56:28 | call to user_input | ArgumentNode is missing PostUpdateNode. | | by_reference.cpp:57:8:57:8 | s | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:57:10:57:22 | call to getIndirectly | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:62:25:62:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | | by_reference.cpp:63:8:63:8 | s | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:68:21:68:30 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:69:22:69:23 | & ... | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:22:13:22:13 | 0 | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:22:16:22:16 | 0 | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:44:12:44:12 | call to a | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:45:12:45:12 | call to b | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:55:13:55:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:56:13:56:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:57:13:57:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:58:13:58:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:34:11:34:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:34:25:34:25 | 0 | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:35:14:35:23 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:36:11:36:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:36:25:36:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:34:11:34:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:34:14:34:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:35:14:35:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:36:11:36:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:36:14:36:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:39:12:39:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:40:12:40:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:41:12:41:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:42:12:42:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected index 1bbc904b3f4..1714355138c 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -24,315 +24,3 @@ postIsInSameCallable reverseRead storeIsPostUpdate argHasPostUpdate -| A.cpp:9:9:9:9 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| A.cpp:14:9:14:9 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| A.cpp:31:14:31:21 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:31:14:31:21 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:31:20:31:20 | c | ArgumentNode is missing PostUpdateNode. | -| A.cpp:38:7:38:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| A.cpp:39:7:39:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| A.cpp:40:5:40:6 | cc | ArgumentNode is missing PostUpdateNode. | -| A.cpp:40:15:40:21 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:41:5:41:6 | ct | ArgumentNode is missing PostUpdateNode. | -| A.cpp:41:15:41:21 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:41:15:41:21 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:41:15:41:21 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:42:10:42:12 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:43:10:43:12 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:47:12:47:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:47:12:47:18 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:48:20:48:20 | c | ArgumentNode is missing PostUpdateNode. | -| A.cpp:49:10:49:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:54:12:54:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:54:12:54:18 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:55:5:55:5 | b | ArgumentNode is missing PostUpdateNode. | -| A.cpp:55:12:55:19 | (C *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:55:12:55:19 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:55:12:55:19 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:56:10:56:10 | b | ArgumentNode is missing PostUpdateNode. | -| A.cpp:56:10:56:17 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:57:10:57:32 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:57:11:57:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:57:11:57:24 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:57:17:57:23 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:57:17:57:23 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:62:13:62:19 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:62:13:62:19 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:64:17:64:18 | b1 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:64:21:64:28 | (C *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:64:21:64:28 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:64:21:64:28 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:65:10:65:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:66:10:66:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:71:13:71:19 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:71:13:71:19 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:73:21:73:22 | b1 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:73:25:73:32 | (C *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:73:25:73:32 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:73:25:73:32 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:74:10:74:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:75:10:75:14 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:81:17:81:18 | b1 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:81:21:81:21 | c | ArgumentNode is missing PostUpdateNode. | -| A.cpp:89:15:89:21 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:89:15:89:21 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:90:7:90:8 | b2 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:90:15:90:15 | c | ArgumentNode is missing PostUpdateNode. | -| A.cpp:98:12:98:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:99:14:99:21 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:99:14:99:21 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:101:8:101:9 | (C *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:107:12:107:16 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:116:12:116:19 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:116:12:116:19 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:120:12:120:16 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:126:5:126:5 | b | ArgumentNode is missing PostUpdateNode. | -| A.cpp:126:12:126:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:126:12:126:18 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:130:12:130:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:130:12:130:18 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:131:8:131:8 | b | ArgumentNode is missing PostUpdateNode. | -| A.cpp:132:10:132:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:142:14:142:20 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:142:14:142:20 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:143:25:143:31 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:143:25:143:31 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:150:12:150:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:150:12:150:18 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:151:12:151:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:151:12:151:24 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:151:18:151:18 | b | ArgumentNode is missing PostUpdateNode. | -| A.cpp:151:21:151:21 | call to r | ArgumentNode is missing PostUpdateNode. | -| A.cpp:152:10:152:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:153:10:153:16 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:154:10:154:13 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:159:12:159:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:159:12:159:18 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:18:160:60 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:18:160:60 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:29:160:29 | b | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:32:160:59 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:32:160:59 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:43:160:49 | (B *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:160:52:160:58 | (MyList *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:161:18:161:40 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:161:18:161:40 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:161:29:161:35 | (B *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:161:38:161:39 | l1 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:162:18:162:40 | Constant | ArgumentNode is missing PostUpdateNode. | -| A.cpp:162:18:162:40 | new | ArgumentNode is missing PostUpdateNode. | -| A.cpp:162:29:162:35 | (B *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:162:38:162:39 | l2 | ArgumentNode is missing PostUpdateNode. | -| A.cpp:163:10:163:17 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:164:10:164:23 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:165:10:165:29 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:166:10:166:35 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| A.cpp:169:12:169:18 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| B.cpp:6:15:6:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| B.cpp:7:16:7:35 | Constant | ArgumentNode is missing PostUpdateNode. | -| B.cpp:7:16:7:35 | new | ArgumentNode is missing PostUpdateNode. | -| B.cpp:7:25:7:25 | e | ArgumentNode is missing PostUpdateNode. | -| B.cpp:7:28:7:34 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | -| B.cpp:8:16:8:27 | Constant | ArgumentNode is missing PostUpdateNode. | -| B.cpp:8:16:8:27 | new | ArgumentNode is missing PostUpdateNode. | -| B.cpp:8:25:8:26 | b1 | ArgumentNode is missing PostUpdateNode. | -| B.cpp:9:10:9:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| B.cpp:10:10:10:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| B.cpp:15:15:15:27 | Constant | ArgumentNode is missing PostUpdateNode. | -| B.cpp:16:16:16:38 | Constant | ArgumentNode is missing PostUpdateNode. | -| B.cpp:16:16:16:38 | new | ArgumentNode is missing PostUpdateNode. | -| B.cpp:16:28:16:34 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | -| B.cpp:16:37:16:37 | e | ArgumentNode is missing PostUpdateNode. | -| B.cpp:17:16:17:27 | Constant | ArgumentNode is missing PostUpdateNode. | -| B.cpp:17:16:17:27 | new | ArgumentNode is missing PostUpdateNode. | -| B.cpp:17:25:17:26 | b1 | ArgumentNode is missing PostUpdateNode. | -| B.cpp:18:10:18:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| B.cpp:19:10:19:24 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| C.cpp:18:12:18:18 | Constant | ArgumentNode is missing PostUpdateNode. | -| C.cpp:18:12:18:18 | new | ArgumentNode is missing PostUpdateNode. | -| C.cpp:19:5:19:5 | c | ArgumentNode is missing PostUpdateNode. | -| C.cpp:22:12:22:21 | Constant | ArgumentNode is missing PostUpdateNode. | -| C.cpp:24:16:24:25 | Constant | ArgumentNode is missing PostUpdateNode. | -| C.cpp:32:10:32:11 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| D.cpp:22:10:22:11 | b2 | ArgumentNode is missing PostUpdateNode. | -| D.cpp:22:10:22:33 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| D.cpp:22:14:22:20 | call to getBox1 | ArgumentNode is missing PostUpdateNode. | -| D.cpp:28:15:28:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:29:15:29:41 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:29:15:29:41 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:29:24:29:40 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:29:24:29:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:29:33:29:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | -| D.cpp:31:14:31:14 | b | ArgumentNode is missing PostUpdateNode. | -| D.cpp:35:15:35:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:36:15:36:41 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:36:15:36:41 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:36:24:36:40 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:36:24:36:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:36:33:36:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | -| D.cpp:37:8:37:10 | box | ArgumentNode is missing PostUpdateNode. | -| D.cpp:37:21:37:21 | e | ArgumentNode is missing PostUpdateNode. | -| D.cpp:38:14:38:14 | b | ArgumentNode is missing PostUpdateNode. | -| D.cpp:42:15:42:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:43:15:43:41 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:43:15:43:41 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:43:24:43:40 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:43:24:43:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:43:33:43:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | -| D.cpp:44:5:44:5 | b | ArgumentNode is missing PostUpdateNode. | -| D.cpp:45:14:45:14 | b | ArgumentNode is missing PostUpdateNode. | -| D.cpp:49:15:49:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:50:15:50:41 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:50:15:50:41 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:50:24:50:40 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:50:24:50:40 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:50:33:50:39 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | -| D.cpp:51:5:51:5 | b | ArgumentNode is missing PostUpdateNode. | -| D.cpp:51:8:51:14 | call to getBox1 | ArgumentNode is missing PostUpdateNode. | -| D.cpp:51:27:51:27 | e | ArgumentNode is missing PostUpdateNode. | -| D.cpp:52:14:52:14 | b | ArgumentNode is missing PostUpdateNode. | -| D.cpp:56:15:56:24 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:57:16:57:42 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:57:16:57:42 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:57:25:57:41 | Constant | ArgumentNode is missing PostUpdateNode. | -| D.cpp:57:25:57:41 | new | ArgumentNode is missing PostUpdateNode. | -| D.cpp:57:34:57:40 | (Elem *)... | ArgumentNode is missing PostUpdateNode. | -| D.cpp:64:10:64:28 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| E.cpp:21:18:21:23 | buffer | ArgumentNode is missing PostUpdateNode. | -| E.cpp:28:21:28:23 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| E.cpp:29:21:29:29 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| E.cpp:30:21:30:33 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| E.cpp:31:10:31:12 | raw | ArgumentNode is missing PostUpdateNode. | -| E.cpp:32:13:32:18 | buffer | ArgumentNode is missing PostUpdateNode. | -| E.cpp:33:18:33:19 | & ... | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:25:17:25:19 | & ... | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:26:19:26:20 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:27:14:27:15 | s3 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:29:11:29:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:30:11:30:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:31:11:31:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:38:11:38:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:43:13:43:14 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:50:11:50:12 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:55:14:55:15 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:62:14:62:15 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:73:12:73:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:80:12:80:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:87:12:87:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| aliasing.cpp:93:12:93:13 | m1 | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:20:5:20:8 | this | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:20:23:20:27 | value | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:24:19:24:22 | this | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:24:25:24:29 | value | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:40:12:40:15 | this | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:44:26:44:29 | this | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:50:3:50:3 | s | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:50:17:50:26 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:51:8:51:8 | (const S)... | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:51:10:51:20 | call to getDirectly | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:56:3:56:3 | s | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:56:19:56:28 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:57:8:57:8 | (const S)... | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:57:10:57:22 | call to getIndirectly | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:62:3:62:3 | s | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:62:25:62:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:63:8:63:8 | (const S)... | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:68:17:68:18 | & ... | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:68:21:68:30 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | ArgumentNode is missing PostUpdateNode. | -| by_reference.cpp:69:22:69:23 | (const S *)... | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:22:11:22:17 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:22:13:22:13 | 0 | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:22:16:22:16 | 0 | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:44:10:44:10 | f | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:44:12:44:12 | call to a | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:45:10:45:10 | f | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:45:12:45:12 | call to b | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:50:7:50:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:51:7:51:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:52:7:52:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:53:7:53:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:55:6:55:6 | f | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:55:13:55:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:56:6:56:6 | f | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:56:13:56:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:57:6:57:6 | f | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:57:13:57:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:58:6:58:6 | f | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:58:13:58:22 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:61:7:61:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:64:7:64:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:67:7:67:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| complex.cpp:70:7:70:8 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:28:10:28:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:29:10:29:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:34:9:34:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:34:11:34:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:34:25:34:25 | 0 | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:35:9:35:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:35:14:35:23 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:36:9:36:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:36:11:36:20 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:36:25:36:34 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:37:9:37:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:40:9:40:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:43:9:43:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:46:9:46:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| constructors.cpp:49:9:49:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:28:10:28:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:28:12:28:12 | call to a | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:29:10:29:10 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:29:12:29:12 | call to b | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:34:9:34:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:34:11:34:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:34:14:34:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:35:9:35:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:35:11:35:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:35:14:35:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:36:9:36:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:36:11:36:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:36:14:36:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:37:9:37:9 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:37:11:37:11 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:37:14:37:14 | 0 | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:39:5:39:5 | f | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:39:12:39:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:40:5:40:5 | g | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:40:12:40:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:41:5:41:5 | h | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:41:12:41:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:42:5:42:5 | h | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:42:12:42:21 | call to user_input | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:45:9:45:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:48:9:48:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:51:9:51:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| simple.cpp:54:9:54:9 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:15:12:15:12 | a | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:16:12:16:12 | b | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:22:11:22:11 | a | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:23:11:23:11 | b | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:24:10:24:12 | & ... | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:31:23:31:23 | a | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:32:23:32:23 | b | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:33:25:33:25 | a | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:34:25:34:25 | b | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:36:10:36:24 | & ... | ArgumentNode is missing PostUpdateNode. | -| struct_init.c:46:16:46:24 | pointerAB | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected index 0664248b431..52963b455e2 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected @@ -91,196 +91,8 @@ postIsInSameCallable reverseRead storeIsPostUpdate argHasPostUpdate -| CPP-309.cpp:7:5:7:20 | | ArgumentNode is missing PostUpdateNode. | -| CPP-309.cpp:7:9:7:9 | 2 | ArgumentNode is missing PostUpdateNode. | -| CPP-309.cpp:7:12:7:12 | 3 | ArgumentNode is missing PostUpdateNode. | -| CPP-309.cpp:11:13:11:13 | 1 | ArgumentNode is missing PostUpdateNode. | -| VacuousDestructorCall.cpp:10:18:10:18 | i | ArgumentNode is missing PostUpdateNode. | -| abortingfunctions.cpp:45:13:45:13 | 0 | ArgumentNode is missing PostUpdateNode. | -| abortingfunctions.cpp:45:16:45:16 | 0 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:14:16:36 | | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:18:16:19 | 11 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:22:16:23 | 22 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:30:16:31 | 33 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:34:16:35 | 44 | ArgumentNode is missing PostUpdateNode. | -| bad_asts.cpp:16:25:16:25 | 1 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:8:32:8:32 | 0 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:8:35:8:37 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:8:40:8:40 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:10:20:10:26 | ... != ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:20:33:20:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:21:33:21:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:21:38:21:38 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:22:34:22:36 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:22:39:22:39 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:28:31:28:38 | ... == ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:34:34:34:34 | x | ArgumentNode is missing PostUpdateNode. | -| builtin.c:39:25:39:27 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:39:30:39:30 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:39:33:39:33 | 1 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:43:26:43:28 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:43:37:43:37 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:45:33:45:41 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:47:24:47:30 | Hello | ArgumentNode is missing PostUpdateNode. | -| builtin.c:47:33:47:35 | 101 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:47:38:47:38 | 5 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:51:41:51:43 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:51:46:51:46 | 0 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:54:41:54:41 | 0 | ArgumentNode is missing PostUpdateNode. | -| builtin.cpp:14:40:14:44 | ... - ... | ArgumentNode is missing PostUpdateNode. | | builtin.cpp:15:31:15:35 | * ... | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:16:20:16:20 | x | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:26:24:26:24 | x | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:41:23:41:23 | x | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:23:48:24 | - ... | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:35:48:36 | - ... | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:53:48:53 | x | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:9:30:13 | call to C1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:12:30:12 | 1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:18:30:22 | call to C1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:21:30:21 | 2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:9:33:13 | call to C1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:12:33:12 | 3 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:18:33:22 | call to C1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:21:33:21 | 3 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:9:39:13 | call to C2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:12:39:12 | 1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:18:39:22 | call to C2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:21:39:21 | 2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:9:42:13 | call to C2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:12:42:12 | 3 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:18:42:22 | call to C2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:21:42:21 | 3 | ArgumentNode is missing PostUpdateNode. | -| constructorinitializer.cpp:8:6:8:10 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| constructorinitializer.cpp:8:13:8:17 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:28:21:28:21 | (__end) | ArgumentNode is missing PostUpdateNode. | | cpp11.cpp:77:5:77:17 | unaryFunction | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:77:19:77:21 | arg | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:77:19:77:21 | arg | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:77:19:77:21 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:11:82:14 | arg2 | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:11:82:14 | arg2 | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:11:82:14 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:17:82:55 | [...](...){...} | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:17:82:55 | [...](...){...} | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:30:82:52 | arg1 | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:45:82:48 | arg1 | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:45:82:48 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:51:82:51 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:51:82:51 | x | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:51:82:51 | x | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:12:88:22 | doSomething | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:25:88:30 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:29:88:29 | 1 | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:33:88:38 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:37:88:37 | 2 | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:5:15:45 | | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:38:15:41 | args | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:38:15:41 | args | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:38:15:41 | p#2 | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:19:13:19:13 | 1 | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:19:16:19:16 | 2 | ArgumentNode is missing PostUpdateNode. | | destructors.cpp:52:14:52:16 | ref | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:377:16:377:16 | x | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:377:19:377:19 | y | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:381:32:381:32 | x | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:381:35:381:35 | y | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:552:16:552:16 | 5 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:585:20:585:26 | %d %s | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:585:29:585:29 | 1 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:585:32:585:39 | string | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:617:15:617:21 | hello | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:619:24:619:29 | test | ArgumentNode is missing PostUpdateNode. | | ir.cpp:623:5:623:5 | r | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:624:5:624:5 | p | ArgumentNode is missing PostUpdateNode. | | ir.cpp:625:5:625:5 | s | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:653:38:653:38 | 0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:654:40:654:40 | 1 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:655:32:655:32 | 2 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:662:13:662:18 | test | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:700:7:700:7 | 5 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:709:14:709:14 | x | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:709:17:709:17 | y | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:721:41:721:47 | 0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:721:50:721:52 | 111 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:731:32:731:46 | String object | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:736:18:736:18 | s | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:745:8:745:8 | base_s | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:754:8:754:8 | * ... | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:754:8:754:8 | middle_s | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:763:8:763:8 | * ... | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:763:8:763:8 | derived_s | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:808:7:808:7 | m | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:809:7:809:13 | call to Base | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:809:13:809:13 | m | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:810:7:810:26 | call to Base | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:810:25:810:25 | m | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:816:16:816:16 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:817:28:817:28 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:822:7:822:7 | d | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:823:7:823:13 | call to Base | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:823:13:823:13 | d | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:824:7:824:26 | call to Base | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:824:25:824:25 | d | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:830:17:830:17 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:831:29:831:29 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:868:10:868:11 | | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:942:3:942:15 | | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:942:7:942:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:945:3:945:27 | | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:945:7:945:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:945:20:945:26 | hello | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:947:3:947:25 | | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:947:7:947:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:947:25:947:25 | 128 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:953:3:953:18 | | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:953:7:953:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:956:3:956:27 | | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:956:7:956:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:956:28:956:28 | 128 | ArgumentNode is missing PostUpdateNode. | -| membercallexpr_args.cpp:10:10:10:14 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| membercallexpr_args.cpp:10:17:10:21 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| misc.c:83:14:83:14 | i | ArgumentNode is missing PostUpdateNode. | -| misc.c:83:17:83:17 | j | ArgumentNode is missing PostUpdateNode. | -| misc.c:84:16:84:16 | i | ArgumentNode is missing PostUpdateNode. | -| misc.c:84:19:84:19 | j | ArgumentNode is missing PostUpdateNode. | -| misc.c:147:16:147:16 | i | ArgumentNode is missing PostUpdateNode. | -| misc.c:147:19:147:19 | j | ArgumentNode is missing PostUpdateNode. | -| misc.c:228:31:228:40 | global_int | ArgumentNode is missing PostUpdateNode. | -| misc.c:229:32:229:41 | global_int | ArgumentNode is missing PostUpdateNode. | -| misc.c:230:27:230:36 | global_int | ArgumentNode is missing PostUpdateNode. | -| misc.c:231:29:231:38 | global_int | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:13:21:13:35 | Hello, world! | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:14:21:14:21 | 0 | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:28:26:28:28 | 256 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:11:12:11:14 | 101 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:14:16:14:18 | 102 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:18:16:18:18 | 103 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:21:16:21:18 | 104 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:24:12:24:14 | 105 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:28:12:28:14 | 101 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:31:16:31:18 | 106 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:35:16:35:18 | 107 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:38:16:38:18 | 108 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:41:12:41:14 | 109 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:48:10:48:12 | 201 | ArgumentNode is missing PostUpdateNode. | -| newexpr.cpp:8:8:8:12 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| newexpr.cpp:8:15:8:19 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| no_dynamic_init.cpp:5:12:5:35 | Goodbye cruel world.\n | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:19:15:19:22 | | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:20:18:20:30 | | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:21:18:21:34 | | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:26:31:26:53 | | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:8:12:8:21 | Got %d\n | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:8:24:8:24 | i | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:19:7:19:7 | 3 | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:21:7:21:7 | 4 | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:23:46:23:50 | 0 | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:24:42:24:45 | 1 | ArgumentNode is missing PostUpdateNode. | -| staticlocals.cpp:27:27:27:29 | two | ArgumentNode is missing PostUpdateNode. | -| staticlocals.cpp:28:27:28:27 | 2 | ArgumentNode is missing PostUpdateNode. | -| staticmembercallexpr_args.cpp:10:9:10:13 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| staticmembercallexpr_args.cpp:10:16:10:20 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| stmt_expr.cpp:13:18:13:18 | 1 | ArgumentNode is missing PostUpdateNode. | -| stmt_expr.cpp:30:20:30:20 | 3 | ArgumentNode is missing PostUpdateNode. | -| vla.c:5:27:5:33 | access to array | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index 19877a98a30..b569b63cb61 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -767,6 +767,8 @@ uniqueNodeToString | duff.c:3:14:3:14 | x | Node should have one toString but has 2. | | duff.c:4:13:4:13 | i | Node should have one toString but has 2. | | duff.c:4:13:4:13 | x | Node should have one toString but has 2. | +| ir.cpp:888:6:888:16 | (no string representation) | Node should have one toString but has 0. | +| misc.c:197:6:197:9 | (no string representation) | Node should have one toString but has 0. | | newexpr.cpp:3:9:3:9 | i | Node should have one toString but has 2. | | newexpr.cpp:3:9:3:9 | x | Node should have one toString but has 2. | | newexpr.cpp:3:16:3:16 | j | Node should have one toString but has 2. | @@ -784,6 +786,7 @@ uniqueNodeToString | switchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | | switchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | missingToString +| Nodes without toString: 2 | parameterCallable localFlowIsLocal compatibleTypesReflexive @@ -796,310 +799,3 @@ postIsInSameCallable reverseRead storeIsPostUpdate argHasPostUpdate -| CPP-309.cpp:7:5:7:20 | Constant | ArgumentNode is missing PostUpdateNode. | -| CPP-309.cpp:7:9:7:9 | 2 | ArgumentNode is missing PostUpdateNode. | -| CPP-309.cpp:7:12:7:12 | 3 | ArgumentNode is missing PostUpdateNode. | -| CPP-309.cpp:11:13:11:13 | 1 | ArgumentNode is missing PostUpdateNode. | -| VacuousDestructorCall.cpp:10:18:10:18 | i | ArgumentNode is missing PostUpdateNode. | -| VacuousDestructorCall.cpp:10:21:10:22 | & ... | ArgumentNode is missing PostUpdateNode. | -| abortingfunctions.cpp:45:13:45:13 | 0 | ArgumentNode is missing PostUpdateNode. | -| abortingfunctions.cpp:45:16:45:16 | 0 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:14:16:36 | Constant | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:14:16:36 | new | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:18:16:19 | 11 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:22:16:23 | 22 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:30:16:31 | 33 | ArgumentNode is missing PostUpdateNode. | -| allocators.cpp:16:34:16:35 | 44 | ArgumentNode is missing PostUpdateNode. | -| bad_asts.cpp:16:5:16:5 | s | ArgumentNode is missing PostUpdateNode. | -| bad_asts.cpp:16:25:16:25 | 1 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:8:32:8:32 | 0 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:8:35:8:37 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:8:40:8:40 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:10:20:10:26 | (bool)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:20:33:20:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:21:33:21:35 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:21:38:21:38 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:22:34:22:36 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:22:39:22:39 | y | ArgumentNode is missing PostUpdateNode. | -| builtin.c:28:31:28:38 | ... == ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:34:22:34:31 | (volatile void *)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:34:34:34:34 | x | ArgumentNode is missing PostUpdateNode. | -| builtin.c:39:25:39:27 | (unsigned int)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:39:30:39:30 | (unsigned int)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:39:33:39:33 | (unsigned int)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:39:36:39:45 | & ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:43:26:43:28 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:43:31:43:37 | (long)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:43:40:43:49 | & ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:45:33:45:41 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:47:24:47:30 | (const void *)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:47:33:47:35 | 101 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:47:38:47:38 | (unsigned long)... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:51:29:51:38 | & ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:51:41:51:43 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:51:46:51:46 | 0 | ArgumentNode is missing PostUpdateNode. | -| builtin.c:54:28:54:38 | & ... | ArgumentNode is missing PostUpdateNode. | -| builtin.c:54:41:54:41 | 0 | ArgumentNode is missing PostUpdateNode. | -| builtin.cpp:10:24:10:24 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| builtin.cpp:14:40:14:44 | (unsigned long)... | ArgumentNode is missing PostUpdateNode. | -| builtin.cpp:15:31:15:35 | * ... | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:3:13:3:22 | Constant | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:16:6:16:20 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:16:20:16:20 | x | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:26:10:26:24 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:26:24:26:24 | x | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:41:9:41:23 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:41:23:41:23 | x | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:16:48:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:23:48:24 | - ... | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:27:48:31 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:35:48:36 | - ... | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:39:48:53 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| condition_decls.cpp:48:53:48:53 | x | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:9:30:13 | (const C1)... | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:12:30:12 | 1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:18:30:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:30:21:30:21 | 2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:9:33:13 | (const C1)... | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:12:33:12 | 3 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:18:33:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:33:21:33:21 | 3 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:9:39:13 | (const C2)... | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:12:39:12 | 1 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:18:39:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:39:21:39:21 | 2 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:9:42:13 | (const C2)... | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:12:42:12 | 3 | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:18:42:22 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| conditional_destructors.cpp:42:21:42:21 | 3 | ArgumentNode is missing PostUpdateNode. | -| constructorinitializer.cpp:8:4:8:4 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| constructorinitializer.cpp:8:6:8:10 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| constructorinitializer.cpp:8:13:8:17 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:77:5:77:17 | (const lambda [] type at line 82, col. 17)... | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:77:19:77:21 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:77:19:77:21 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:11:82:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:11:82:14 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:17:82:55 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:17:82:55 | [...](...){...} | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:45:82:48 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:45:82:48 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:51:82:51 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:82:51:82:51 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:12:88:22 | doSomething | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:25:88:30 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:29:88:29 | 1 | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:33:88:38 | call to Val | ArgumentNode is missing PostUpdateNode. | -| cpp11.cpp:88:37:88:37 | 2 | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:5:15:45 | Constant | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:5:15:45 | new | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:19:15:21 | ptr | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:38:15:41 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:15:38:15:41 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:19:10:19:10 | p | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:19:13:19:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| cpp17.cpp:19:16:19:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| defconstructornewexpr.cpp:4:2:4:6 | Constant | ArgumentNode is missing PostUpdateNode. | -| defdestructordeleteexpr.cpp:4:9:4:15 | Constant | ArgumentNode is missing PostUpdateNode. | -| deleteexpr.cpp:7:9:7:15 | Constant | ArgumentNode is missing PostUpdateNode. | -| destructors.cpp:50:9:50:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| destructors.cpp:52:14:52:16 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | & ... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | & ... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | & ... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (Base *)... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (Middle *)... | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (__begin) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (__begin) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference dereference) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| file://:0:0:0:0 | this | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:377:16:377:16 | x | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:377:19:377:19 | y | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:381:32:381:32 | x | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:381:35:381:35 | y | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:552:16:552:16 | 5 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:585:20:585:26 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:585:29:585:29 | 1 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:585:32:585:39 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:616:12:616:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:617:12:617:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:617:15:617:21 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:619:12:619:13 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:619:24:619:29 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:623:5:623:5 | (const String)... | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:624:5:624:5 | (const String *)... | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:625:5:625:5 | (const String)... | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:653:9:653:12 | this | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:653:38:653:38 | 0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:654:10:654:14 | * ... | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:654:40:654:40 | 1 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:655:32:655:32 | 2 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:662:9:662:19 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:662:13:662:18 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:663:5:663:5 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:700:7:700:7 | 5 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:709:14:709:14 | x | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:709:17:709:17 | y | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:721:41:721:47 | (void *)... | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:721:50:721:52 | 111 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:736:5:736:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:736:18:736:18 | s | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:745:8:745:8 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:748:10:748:10 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:751:3:751:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:757:12:757:12 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:757:12:757:12 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:760:3:760:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:760:3:760:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:766:13:766:13 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:766:13:766:13 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:769:3:769:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:769:3:769:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:775:15:775:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:775:15:775:15 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:778:3:778:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:778:3:778:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:784:15:784:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:784:15:784:15 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:787:3:787:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:787:3:787:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:793:15:793:15 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:796:3:796:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:796:3:796:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:796:3:796:3 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:796:3:796:3 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:800:8:800:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:801:10:801:10 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:802:11:802:11 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:808:3:808:3 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:808:7:808:7 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:809:3:809:3 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:809:7:809:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:809:13:809:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:810:3:810:3 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:810:7:810:26 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:810:25:810:25 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:816:3:816:3 | m | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:816:7:816:16 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:817:3:817:3 | m | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:817:7:817:29 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:822:3:822:3 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:822:7:822:7 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:823:3:823:3 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:823:7:823:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:823:13:823:13 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:824:3:824:3 | b | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:824:7:824:26 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:824:25:824:25 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:830:3:830:3 | d | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:830:7:830:17 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:831:3:831:3 | d | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:831:7:831:30 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:846:8:846:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:846:8:846:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:850:19:850:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:851:22:851:22 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:867:1:867:14 | this | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:868:10:868:11 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:941:3:941:9 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:942:3:942:15 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:942:7:942:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:943:3:943:11 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:944:3:944:14 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:944:3:944:14 | new | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:945:3:945:27 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:945:3:945:27 | new | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:945:7:945:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:945:20:945:26 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:946:3:946:17 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:946:18:946:18 | 128 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:947:3:947:25 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:947:7:947:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:947:25:947:25 | 128 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:951:3:951:13 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:952:3:952:12 | Mul | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:953:3:953:18 | Mul | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:953:7:953:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:954:3:954:15 | Mul | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:955:3:955:20 | Mul | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:955:21:955:21 | 128 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:956:3:956:27 | Constant | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:956:7:956:10 | 1.0 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:956:28:956:28 | 128 | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:957:3:957:36 | Mul | ArgumentNode is missing PostUpdateNode. | -| ir.cpp:958:3:958:24 | Mul | ArgumentNode is missing PostUpdateNode. | -| membercallexpr.cpp:8:2:8:2 | c | ArgumentNode is missing PostUpdateNode. | -| membercallexpr_args.cpp:10:5:10:5 | d | ArgumentNode is missing PostUpdateNode. | -| membercallexpr_args.cpp:10:10:10:14 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| membercallexpr_args.cpp:10:17:10:21 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| misc.c:147:16:147:16 | i | ArgumentNode is missing PostUpdateNode. | -| misc.c:147:19:147:19 | j | ArgumentNode is missing PostUpdateNode. | -| misc.c:228:31:228:40 | global_int | ArgumentNode is missing PostUpdateNode. | -| misc.c:229:32:229:41 | global_int | ArgumentNode is missing PostUpdateNode. | -| misc.c:230:27:230:36 | global_int | ArgumentNode is missing PostUpdateNode. | -| misc.c:231:29:231:38 | global_int | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:13:21:13:35 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:14:21:14:21 | (const char *)... | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:28:18:28:23 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:28:26:28:28 | 256 | ArgumentNode is missing PostUpdateNode. | -| ms_assume.cpp:28:31:28:31 | s | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:11:7:11:10 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:11:12:11:14 | 101 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:28:7:28:10 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:28:12:28:14 | 101 | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:48:5:48:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| ms_try_mix.cpp:48:10:48:12 | 201 | ArgumentNode is missing PostUpdateNode. | -| newexpr.cpp:8:2:8:20 | Constant | ArgumentNode is missing PostUpdateNode. | -| newexpr.cpp:8:2:8:20 | new | ArgumentNode is missing PostUpdateNode. | -| newexpr.cpp:8:8:8:12 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| newexpr.cpp:8:15:8:19 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| no_dynamic_init.cpp:5:12:5:35 | array to pointer conversion | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:19:15:19:22 | Constant | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:20:18:20:30 | Constant | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:21:18:21:34 | Mul | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:26:31:26:53 | Constant | ArgumentNode is missing PostUpdateNode. | -| ops.cpp:26:31:26:53 | new | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:8:12:8:21 | (char *)... | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:8:24:8:24 | i | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:19:7:19:7 | 3 | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:21:7:21:7 | 4 | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:25:5:25:8 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| parameterinitializer.cpp:27:3:27:6 | my_c | ArgumentNode is missing PostUpdateNode. | -| pmcallexpr.cpp:8:11:8:11 | g | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:23:6:23:8 | obj | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:23:21:23:44 | call to getFunctionMemberPointer | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:23:46:23:50 | 0 | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:24:17:24:40 | call to getFunctionMemberPointer | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:24:42:24:45 | 1 | ArgumentNode is missing PostUpdateNode. | -| pointer_to_member.cpp:27:12:27:14 | obj | ArgumentNode is missing PostUpdateNode. | -| static_init_templates.cpp:20:12:20:12 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| static_init_templates.cpp:31:10:31:11 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| static_init_templates.cpp:236:7:236:7 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| static_init_templates.cpp:240:7:240:7 | FieldAddress | ArgumentNode is missing PostUpdateNode. | -| static_init_templates.cpp:249:21:249:23 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| static_init_templates.cpp:250:17:250:19 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| static_init_templates.cpp:251:20:251:23 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| staticlocals.cpp:29:14:29:14 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| staticmembercallexpr.cpp:8:2:8:2 | c | ArgumentNode is missing PostUpdateNode. | -| staticmembercallexpr_args.cpp:10:4:10:4 | d | ArgumentNode is missing PostUpdateNode. | -| staticmembercallexpr_args.cpp:10:9:10:13 | ... + ... | ArgumentNode is missing PostUpdateNode. | -| staticmembercallexpr_args.cpp:10:16:10:20 | ... - ... | ArgumentNode is missing PostUpdateNode. | -| stmt_expr.cpp:13:16:13:16 | VariableAddress | ArgumentNode is missing PostUpdateNode. | -| stmt_expr.cpp:13:18:13:18 | 1 | ArgumentNode is missing PostUpdateNode. | -| stream_it.cpp:19:13:19:14 | (reference to) | ArgumentNode is missing PostUpdateNode. | -| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase | ArgumentNode is missing PostUpdateNode. | -| try_catch.cpp:13:5:13:16 | VariableAddress | ArgumentNode is missing PostUpdateNode. | From 663dc24753ea66e0e937fca4406cf37bb6eab8fe Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Mar 2020 18:29:08 +0200 Subject: [PATCH 194/459] Python: Apply suggestion from Taus rewrote the qldoc to explain it as well. --- .../examples/custom-sanitizer/Taint.qll | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll index 15a2097eb26..d721ed47989 100644 --- a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll +++ b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll @@ -33,33 +33,31 @@ class MySanitizerHandlingNot extends Sanitizer { /** The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. */ override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { taint instanceof ExternalStringKind and - clears_taint_on_true(_, test.getTest(), test.getSense(), test) + clears_taint_on_true(test.getTest(), test.getSense(), test) } /** * Helper predicate that recurses into any nesting of `not` * * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and - * ensure that `test` is a part of this `PyEdgeRefinement`. Without including `PyEdgeRefinement` as an argument - * *any* `CallNode c` to `test.is_safe` would be a result of this predicate, since (c, c, true) would hold. + * ensure that `test` is a part of this `PyEdgeRefinement` (instead of just taking the + * `edge_refinement.getInput().getAUse()` part as a part of the predicate). Without including + * `PyEdgeRefinement` as an argument *any* `CallNode c` to `test.is_safe` would be a result of + * this predicate, since the tuple where `test = c` and `sense = true` would hold. */ private predicate clears_taint_on_true( - CallNode final_test, ControlFlowNode test, boolean sense, PyEdgeRefinement edge_refinement + ControlFlowNode test, boolean sense, PyEdgeRefinement edge_refinement ) { + edge_refinement.getTest().getNode().(Expr).getASubExpression*() = test.getNode() and ( - edge_refinement.getTest().getNode().(Expr).getASubExpression*() = test.getNode() and - test.getNode().(Expr).getASubExpression*() = final_test.getNode() - ) and - ( - final_test = test and - final_test = Value::named("test.is_safe").getACall() and - edge_refinement.getInput().getAUse() = final_test.getAnArg() and + test = Value::named("test.is_safe").getACall() and + edge_refinement.getInput().getAUse() = test.(CallNode).getAnArg() and sense = true or test.(UnaryExprNode).getNode().getOp() instanceof Not and exists(ControlFlowNode nested_test | nested_test = test.(UnaryExprNode).getOperand() and - clears_taint_on_true(final_test, nested_test, sense.booleanNot(), edge_refinement) + clears_taint_on_true(nested_test, sense.booleanNot(), edge_refinement) ) ) } From fad03e77ccb3017e4009b6718dc5a4fcafa547ea Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Mar 2020 18:31:16 +0200 Subject: [PATCH 195/459] Python: Move helper predicate outside of class otherwise the helper predicate can (and sometimes will) be evaluated once _per_ instance of that class. --- .../examples/custom-sanitizer/Taint.qll | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll index d721ed47989..b5c8445fe03 100644 --- a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll +++ b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll @@ -35,32 +35,32 @@ class MySanitizerHandlingNot extends Sanitizer { taint instanceof ExternalStringKind and clears_taint_on_true(test.getTest(), test.getSense(), test) } +} - /** - * Helper predicate that recurses into any nesting of `not` - * - * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and - * ensure that `test` is a part of this `PyEdgeRefinement` (instead of just taking the - * `edge_refinement.getInput().getAUse()` part as a part of the predicate). Without including - * `PyEdgeRefinement` as an argument *any* `CallNode c` to `test.is_safe` would be a result of - * this predicate, since the tuple where `test = c` and `sense = true` would hold. - */ - private predicate clears_taint_on_true( - ControlFlowNode test, boolean sense, PyEdgeRefinement edge_refinement - ) { - edge_refinement.getTest().getNode().(Expr).getASubExpression*() = test.getNode() and - ( - test = Value::named("test.is_safe").getACall() and - edge_refinement.getInput().getAUse() = test.(CallNode).getAnArg() and - sense = true - or - test.(UnaryExprNode).getNode().getOp() instanceof Not and - exists(ControlFlowNode nested_test | - nested_test = test.(UnaryExprNode).getOperand() and - clears_taint_on_true(nested_test, sense.booleanNot(), edge_refinement) - ) +/** + * Helper predicate that recurses into any nesting of `not` + * + * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and + * ensure that `test` is a part of this `PyEdgeRefinement` (instead of just taking the + * `edge_refinement.getInput().getAUse()` part as a part of the predicate). Without including + * `PyEdgeRefinement` as an argument *any* `CallNode c` to `test.is_safe` would be a result of + * this predicate, since the tuple where `test = c` and `sense = true` would hold. + */ +private predicate clears_taint_on_true( + ControlFlowNode test, boolean sense, PyEdgeRefinement edge_refinement +) { + edge_refinement.getTest().getNode().(Expr).getASubExpression*() = test.getNode() and + ( + test = Value::named("test.is_safe").getACall() and + edge_refinement.getInput().getAUse() = test.(CallNode).getAnArg() and + sense = true + or + test.(UnaryExprNode).getNode().getOp() instanceof Not and + exists(ControlFlowNode nested_test | + nested_test = test.(UnaryExprNode).getOperand() and + clears_taint_on_true(nested_test, sense.booleanNot(), edge_refinement) ) - } + ) } class TestConfig extends TaintTracking::Configuration { From 6127d8b8f4a4af4137f83dcd92b3300aea620c50 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Mar 2020 18:32:31 +0200 Subject: [PATCH 196/459] Python: Fixup comment alignment --- .../examples/custom-sanitizer/Taint.qll | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll index b5c8445fe03..9b2216dbcd9 100644 --- a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll +++ b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll @@ -38,14 +38,14 @@ class MySanitizerHandlingNot extends Sanitizer { } /** - * Helper predicate that recurses into any nesting of `not` - * - * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and - * ensure that `test` is a part of this `PyEdgeRefinement` (instead of just taking the - * `edge_refinement.getInput().getAUse()` part as a part of the predicate). Without including - * `PyEdgeRefinement` as an argument *any* `CallNode c` to `test.is_safe` would be a result of - * this predicate, since the tuple where `test = c` and `sense = true` would hold. - */ + * Helper predicate that recurses into any nesting of `not` + * + * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and + * ensure that `test` is a part of this `PyEdgeRefinement` (instead of just taking the + * `edge_refinement.getInput().getAUse()` part as a part of the predicate). Without including + * `PyEdgeRefinement` as an argument *any* `CallNode c` to `test.is_safe` would be a result of + * this predicate, since the tuple where `test = c` and `sense = true` would hold. + */ private predicate clears_taint_on_true( ControlFlowNode test, boolean sense, PyEdgeRefinement edge_refinement ) { From 40c3b5468f35601a7b84bbc6a5fcd5a54ddb642d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Mon, 30 Mar 2020 18:55:14 +0200 Subject: [PATCH 197/459] Fix QHelp/XML syntax --- .../Security/CWE/CWE-036/OpenStream.qhelp | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp index fcb7f6313ee..d3113576b6d 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp @@ -2,40 +2,34 @@ "-//Semmle//qhelp//EN" "qhelp.dtd"> +

    Calling openStream on URLs created from remote source can lead to local file disclosure.

    -

    If openStream is called on a java.net.URL, that was created from a remote source an attacker can try to pass absolute URLs starting with file:// or jar:// to access local resources in addition to remote ones.

    -
    - +

    When you construct a URL using java.net.URL from a remote source, make sure to not call openStream on it. Instead fetch the URL with a HTTP Client to access its content. Also validate that the URL uses the correct protocol and host combination.

    -
    - +

    The following example shows an URL that is constructed from a request parameter. Afterwards openStream is called on the URL, potentially leading to a local file access.

    - -
    - +
    • Java Platform, Standard Edition 11, API Specification: Class URL. -
    • +
    - - - +
    +
    From b634b59b9cc54dd9e75dd46224cff9e9c652082d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 30 Mar 2020 18:52:12 +0100 Subject: [PATCH 198/459] C++: Merge the two allocators tests. --- .../allocators/allocators.expected | 46 +++++++++---------- .../library-tests/allocators/allocators.ql | 10 ++-- .../allocators/placement.expected | 2 - .../library-tests/allocators/placement.ql | 4 -- 4 files changed, 29 insertions(+), 33 deletions(-) delete mode 100644 cpp/ql/test/library-tests/allocators/placement.expected delete mode 100644 cpp/ql/test/library-tests/allocators/placement.ql diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index ee67a413692..db0775ab661 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -1,28 +1,28 @@ newExprs -| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | -| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | | -| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | -| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | | -| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | | -| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned | -| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | -| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | -| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | -| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | -| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | +| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | +| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | | | +| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | +| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | | | +| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | | | +| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned | | +| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | | +| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | | +| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | +| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | & ... | +| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | | newArrayExprs -| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n | -| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n | -| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n | -| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n | -| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | -| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n | -| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | -| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | | -| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | | -| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x | -| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | | -| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x | +| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n | | +| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n | | +| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n | | +| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n | | +| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | | +| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n | | +| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | | +| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | | buf | +| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | | | +| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x | | +| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | | | +| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x | | newExprDeallocators | allocators.cpp:52:3:52:14 | new | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:53:3:53:27 | new | String | operator delete(void *, float) -> void | 8 | 8 | | diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index 37603f77a3e..89abd415cb1 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -1,6 +1,6 @@ import default -query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form) { +query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form, string placement) { exists(Function allocator, Type allocatedType | expr.getAllocator() = allocator and sig = allocator.getFullSignature() and @@ -8,13 +8,14 @@ query predicate newExprs(NewExpr expr, string type, string sig, int size, int al type = allocatedType.toString() and size = allocatedType.getSize() and alignment = allocatedType.getAlignment() and - if expr.hasAlignedAllocation() then form = "aligned" else form = "" + if expr.hasAlignedAllocation() then form = "aligned" else form = "" and + if exists(expr.getPlacementPointer()) then placement = expr.getPlacementPointer().toString() else placement = "" ) } query predicate newArrayExprs( NewArrayExpr expr, string t1, string t2, string sig, int size, int alignment, string form, - string extents + string extents, string placement ) { exists(Function allocator, Type arrayType, Type elementType | expr.getAllocator() = allocator and @@ -26,7 +27,8 @@ query predicate newArrayExprs( size = elementType.getSize() and alignment = elementType.getAlignment() and (if expr.hasAlignedAllocation() then form = "aligned" else form = "") and - extents = concat(Expr e | e = expr.getExtent() | e.toString(), ", ") + extents = concat(Expr e | e = expr.getExtent() | e.toString(), ", ") and + if exists(expr.getPlacementPointer()) then placement = expr.getPlacementPointer().toString() else placement = "" ) } diff --git a/cpp/ql/test/library-tests/allocators/placement.expected b/cpp/ql/test/library-tests/allocators/placement.expected deleted file mode 100644 index 5755e349eb3..00000000000 --- a/cpp/ql/test/library-tests/allocators/placement.expected +++ /dev/null @@ -1,2 +0,0 @@ -| allocators.cpp:129:3:129:21 | new | allocators.cpp:129:7:129:13 | & ... | -| allocators.cpp:132:3:132:17 | new[] | allocators.cpp:132:7:132:9 | buf | diff --git a/cpp/ql/test/library-tests/allocators/placement.ql b/cpp/ql/test/library-tests/allocators/placement.ql deleted file mode 100644 index a632c3c5afe..00000000000 --- a/cpp/ql/test/library-tests/allocators/placement.ql +++ /dev/null @@ -1,4 +0,0 @@ -import cpp - -from NewOrNewArrayExpr new -select new, new.getPlacementPointer() as placement From 7938bc4ed0f72a1109d7bb183a8a2dd8ff2bdb1d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Mar 2020 19:57:43 +0200 Subject: [PATCH 199/459] improve alert message for js/useless-assignment-to-local --- .../ql/src/Declarations/DeadStoreOfLocal.ql | 19 ++++++++++++++++++- .../DeadStoreOfLocal.expected | 1 + .../Declarations/DeadStoreOfLocal/tst.js | 8 ++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql index 8fcd88724af..18febd8386d 100644 --- a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql +++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql @@ -29,6 +29,23 @@ predicate deadStoreOfLocal(VarDef vd, PurelyLocalVariable v) { not exists(SsaExplicitDefinition ssa | ssa.defines(vd, v)) } +/** + * Holds if there exists another definition of the variable `v` that dominates `dead`. + */ +predicate hasDominatingDef(VarDef dead, PurelyLocalVariable v) { + exists(VarDef otherDef | not otherDef = dead and otherDef.getAVariable() = v | + dead.getBasicBlock().getASuccessor+() = otherDef.getBasicBlock() + or + exists(ReachableBasicBlock bb, int i, int j | + bb = otherDef.getBasicBlock() and bb = dead.getBasicBlock() + | + bb.defAt(i, v, dead) and + bb.defAt(j, v, otherDef) and + j > i + ) + ) +} + from VarDef dead, PurelyLocalVariable v, string msg where deadStoreOfLocal(dead, v) and @@ -63,7 +80,7 @@ where ( // To avoid confusion about the meaning of "definition" and "declaration" we avoid // the term "definition" when the alert location is a variable declaration. - if dead instanceof VariableDeclarator + if dead instanceof VariableDeclarator and hasDominatingDef(dead, v) then msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten." else msg = "This definition of " + v.getName() + " is useless, since its value is never read." ) diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected index 52143fd3d7b..fd87be61375 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected @@ -10,3 +10,4 @@ | tst.js:51:6:51:11 | x = 23 | The initial value of x is unused, since it is always overwritten. | | tst.js:132:7:132:13 | {x} = o | The initial value of x is unused, since it is always overwritten. | | tst.js:162:6:162:14 | [x] = [0] | The initial value of x is unused, since it is always overwritten. | +| tst.js:172:7:172:17 | nSign = foo | This definition of nSign is useless, since its value is never read. | diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js index c398cf3370e..f19b1656da2 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js @@ -166,3 +166,11 @@ function v() { x; y; }); + +(function() { + if (something()) { + var nSign = foo; + } else { + console.log(nSign); + } +})() From 0cb7d4c82df33e0948a33c7e8f6fbbc531073054 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 30 Mar 2020 20:28:21 +0100 Subject: [PATCH 200/459] C++: Add an explicit test of AllocationFunction and AllocationExpr. --- .../allocators/allocators.expected | 25 +++++++++++++ .../library-tests/allocators/allocators.ql | 36 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index db0775ab661..44847688e1f 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -46,3 +46,28 @@ deleteArrayExprs | allocators.cpp:81:3:81:45 | delete[] | Overaligned | operator delete[](void *, unsigned long, align_val_t) -> void | 256 | 128 | sized aligned | | allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:83:3:83:23 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized | +allocationFunctions +allocationExprs +| allocators.cpp:49:3:49:9 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:50:3:50:15 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:51:3:51:11 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:52:3:52:14 | new | getSizeBytes = 8, requiresDealloc | +| allocators.cpp:53:3:53:27 | new | getSizeBytes = 8, requiresDealloc | +| allocators.cpp:54:3:54:17 | new | getSizeBytes = 256, requiresDealloc | +| allocators.cpp:55:3:55:25 | new | getSizeBytes = 256, requiresDealloc | +| allocators.cpp:68:3:68:12 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | +| allocators.cpp:69:3:69:18 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | +| allocators.cpp:70:3:70:15 | new[] | getSizeExpr = n, getSizeMult = 8, requiresDealloc | +| allocators.cpp:71:3:71:20 | new[] | getSizeExpr = n, getSizeMult = 256, requiresDealloc | +| allocators.cpp:72:3:72:16 | new[] | getSizeBytes = 80, requiresDealloc | +| allocators.cpp:107:3:107:18 | new | getSizeBytes = 1, requiresDealloc | +| allocators.cpp:108:3:108:19 | new[] | getSizeExpr = n, getSizeMult = 1, requiresDealloc | +| allocators.cpp:109:3:109:35 | new | getSizeBytes = 128, requiresDealloc | +| allocators.cpp:110:3:110:37 | new[] | getSizeBytes = 1280, requiresDealloc | +| allocators.cpp:129:3:129:21 | new | getSizeBytes = 4 | +| allocators.cpp:132:3:132:17 | new[] | getSizeBytes = 4 | +| allocators.cpp:135:3:135:26 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:136:3:136:26 | new[] | getSizeBytes = 8, requiresDealloc | +| allocators.cpp:142:13:142:27 | new[] | getSizeExpr = x, getSizeMult = 10, requiresDealloc | +| allocators.cpp:143:13:143:28 | new[] | getSizeBytes = 400, requiresDealloc | +| allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc | diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index 89abd415cb1..e8a0d1b90c3 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -103,3 +103,39 @@ query predicate deleteArrayExprs( ) ) } + +string describeAllocationFunction(AllocationFunction f) { + result = "getSizeArg = " + f.getSizeArg().toString() + or + result = "getSizeMult = " + f.getSizeMult().toString() + or + result = "getReallocPtrArg = " + f.getReallocPtrArg().toString() + or + ( + f.requiresDealloc() and + result = "requiresDealloc" + ) +} + +query predicate allocationFunctions(AllocationFunction f, string descr) { + descr = concat(describeAllocationFunction(f), ", ") +} + +string describeAllocationExpr(AllocationExpr e) { + result = "getSizeExpr = " + e.getSizeExpr().toString() + or + result = "getSizeMult = " + e.getSizeMult().toString() + or + result = "getSizeBytes = " + e.getSizeBytes().toString() + or + result = "getReallocPtr = " + e.getReallocPtr().toString() + or + ( + e.requiresDealloc() and + result = "requiresDealloc" + ) +} + +query predicate allocationExprs(AllocationExpr e, string descr) { + descr = concat(describeAllocationExpr(e), ", ") +} From 40fd1825e9d409081309e59700130a95c20c61ed Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 31 Mar 2020 09:08:32 +0200 Subject: [PATCH 201/459] autoformat --- javascript/ql/src/Declarations/DeadStoreOfLocal.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql index 18febd8386d..9406d5c5c61 100644 --- a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql +++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql @@ -30,8 +30,8 @@ predicate deadStoreOfLocal(VarDef vd, PurelyLocalVariable v) { } /** - * Holds if there exists another definition of the variable `v` that dominates `dead`. - */ + * Holds if there exists another definition of the variable `v` that dominates `dead`. + */ predicate hasDominatingDef(VarDef dead, PurelyLocalVariable v) { exists(VarDef otherDef | not otherDef = dead and otherDef.getAVariable() = v | dead.getBasicBlock().getASuccessor+() = otherDef.getBasicBlock() From aa49b35d2c34c5ee0299ec16d849fe4b9b7e171c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 09:57:02 +0100 Subject: [PATCH 202/459] C++: Add an explicit test of DeallocationFunction and DeallocationExpr as well. --- .../library-tests/allocators/allocators.expected | 14 ++++++++++++++ .../test/library-tests/allocators/allocators.ql | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index 44847688e1f..355660b6d8c 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -71,3 +71,17 @@ allocationExprs | allocators.cpp:142:13:142:27 | new[] | getSizeExpr = x, getSizeMult = 10, requiresDealloc | | allocators.cpp:143:13:143:28 | new[] | getSizeBytes = 400, requiresDealloc | | allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc | +deallocationFunctions +deallocationExprs +| allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 | +| allocators.cpp:60:3:60:38 | delete | getFreedExpr = 0 | +| allocators.cpp:61:3:61:44 | delete | getFreedExpr = 0 | +| allocators.cpp:62:3:62:43 | delete | getFreedExpr = 0 | +| allocators.cpp:63:3:63:47 | delete | getFreedExpr = 0 | +| allocators.cpp:64:3:64:44 | delete | getFreedExpr = 0 | +| allocators.cpp:78:3:78:37 | delete[] | getFreedExpr = 0 | +| allocators.cpp:79:3:79:40 | delete[] | getFreedExpr = 0 | +| allocators.cpp:80:3:80:46 | delete[] | getFreedExpr = 0 | +| allocators.cpp:81:3:81:45 | delete[] | getFreedExpr = 0 | +| allocators.cpp:82:3:82:49 | delete[] | getFreedExpr = 0 | +| allocators.cpp:83:3:83:23 | delete[] | getFreedExpr = call to GetPointer | diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index e8a0d1b90c3..a50fe4be3d4 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -139,3 +139,19 @@ string describeAllocationExpr(AllocationExpr e) { query predicate allocationExprs(AllocationExpr e, string descr) { descr = concat(describeAllocationExpr(e), ", ") } + +string describeDeallocationFunction(DeallocationFunction f) { + result = "getFreedArg = " + f.getFreedArg().toString() +} + +query predicate deallocationFunctions(DeallocationFunction f, string descr) { + descr = concat(describeDeallocationFunction(f), ", ") +} + +string describeDeallocationExpr(DeallocationExpr e) { + result = "getFreedExpr = " + e.getFreedExpr().toString() +} + +query predicate deallocationExprs(DeallocationExpr e, string descr) { + descr = concat(describeDeallocationExpr(e), ", ") +} From ef68bd6bf4b208de16a39d146ef93ce13de1673d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 11:01:29 +0100 Subject: [PATCH 203/459] C++: Add a test of direct calls to operator new / operator dedelete. --- cpp/ql/test/library-tests/allocators/allocators.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/ql/test/library-tests/allocators/allocators.cpp b/cpp/ql/test/library-tests/allocators/allocators.cpp index 6571245f5fc..92241b9c9e3 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.cpp +++ b/cpp/ql/test/library-tests/allocators/allocators.cpp @@ -143,3 +143,9 @@ void multidimensionalNew(int x, int y) { auto p2 = new char[20][20]; auto p3 = new char[x][30][30]; } + +void directOperatorCall() { + void *ptr; + ptr = operator new(sizeof(int)); + operator delete(ptr); +} From 259f714d91c96ec79a5115669bd4deb266df0a48 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 30 Mar 2020 18:11:07 +0100 Subject: [PATCH 204/459] C++: Model operator new and operator new[]. --- cpp/ql/src/semmle/code/cpp/exprs/Expr.qll | 13 +++----- .../cpp/models/implementations/Allocation.qll | 33 +++++++++++++++++++ .../allocators/allocators.expected | 21 ++++++++++++ 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index bb6aa86b4e7..97371919b02 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -2,6 +2,7 @@ import semmle.code.cpp.Element private import semmle.code.cpp.Enclosing private import semmle.code.cpp.internal.ResolveClass private import semmle.code.cpp.internal.AddressConstantExpression +private import semmle.code.cpp.models.implementations.Allocation /** * A C/C++ expression. @@ -804,8 +805,10 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { * call the constructor of `T` but will not allocate memory. */ Expr getPlacementPointer() { - isStandardPlacementNewAllocator(this.getAllocator()) and - result = this.getAllocatorCall().getArgument(1) + result = + this + .getAllocatorCall() + .getArgument(this.getAllocator().(OperatorNewAllocationFunction).getPlacementArgument()) } } @@ -1194,12 +1197,6 @@ private predicate convparents(Expr child, int idx, Element parent) { ) } -private predicate isStandardPlacementNewAllocator(Function operatorNew) { - operatorNew.getName().matches("operator new%") and - operatorNew.getNumberOfParameters() = 2 and - operatorNew.getParameter(1).getType() instanceof VoidPointerType -} - // Pulled out for performance. See QL-796. private predicate hasNoConversions(Expr e) { not e.hasConversion() } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index e2f34fe03cc..81b4a6c8ea6 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -215,6 +215,39 @@ class SizelessAllocationFunction extends AllocationFunction { } } +/** + * An `operator new` or `operator new[]` function that may be associated with a `new` or + * `new[]` expression. Note that `new` and `new[]` are not function calls, but these + * functions may also be called directly. + */ +class OperatorNewAllocationFunction extends AllocationFunction { + OperatorNewAllocationFunction() { + exists(string name | + hasGlobalOrStdName(name) and + ( + // operator new(bytes, ...) + name = "operator new" or + // operator new[](bytes, ...) + name = "operator new[]" + ) + ) + } + + override int getSizeArg() { result = 0 } + + override predicate requiresDealloc() { not exists(getPlacementArgument()) } + + /** + * Gets the position of the placement pointer if this is a placement + * `operator new` function. + */ + int getPlacementArgument() { + getNumberOfParameters() = 2 and + getParameter(1).getType() instanceof VoidPointerType and + result = 1 + } +} + /** * An allocation expression that is a function call, such as call to `malloc`. */ diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index 355660b6d8c..9c598181f04 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -47,15 +47,31 @@ deleteArrayExprs | allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:83:3:83:23 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized | allocationFunctions +| allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc | +| allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc | +| allocators.cpp:9:7:9:18 | operator new | getSizeArg = 0, requiresDealloc | +| allocators.cpp:10:7:10:20 | operator new[] | getSizeArg = 0, requiresDealloc | +| allocators.cpp:121:7:121:18 | operator new | getSizeArg = 0 | +| allocators.cpp:122:7:122:20 | operator new[] | getSizeArg = 0 | +| allocators.cpp:123:7:123:18 | operator new | getSizeArg = 0, requiresDealloc | +| allocators.cpp:124:7:124:20 | operator new[] | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc | allocationExprs | allocators.cpp:49:3:49:9 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:50:3:50:15 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:50:3:50:15 | new | getSizeBytes = 4, requiresDealloc | | allocators.cpp:51:3:51:11 | new | getSizeBytes = 4, requiresDealloc | | allocators.cpp:52:3:52:14 | new | getSizeBytes = 8, requiresDealloc | +| allocators.cpp:53:3:53:27 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:53:3:53:27 | new | getSizeBytes = 8, requiresDealloc | | allocators.cpp:54:3:54:17 | new | getSizeBytes = 256, requiresDealloc | +| allocators.cpp:55:3:55:25 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:55:3:55:25 | new | getSizeBytes = 256, requiresDealloc | | allocators.cpp:68:3:68:12 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | +| allocators.cpp:69:3:69:18 | call to operator new[] | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:69:3:69:18 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | | allocators.cpp:70:3:70:15 | new[] | getSizeExpr = n, getSizeMult = 8, requiresDealloc | | allocators.cpp:71:3:71:20 | new[] | getSizeExpr = n, getSizeMult = 256, requiresDealloc | @@ -64,13 +80,18 @@ allocationExprs | allocators.cpp:108:3:108:19 | new[] | getSizeExpr = n, getSizeMult = 1, requiresDealloc | | allocators.cpp:109:3:109:35 | new | getSizeBytes = 128, requiresDealloc | | allocators.cpp:110:3:110:37 | new[] | getSizeBytes = 1280, requiresDealloc | +| allocators.cpp:129:3:129:21 | call to operator new | getSizeExpr = , getSizeMult = 1 | | allocators.cpp:129:3:129:21 | new | getSizeBytes = 4 | +| allocators.cpp:132:3:132:17 | call to operator new[] | getSizeExpr = , getSizeMult = 1 | | allocators.cpp:132:3:132:17 | new[] | getSizeBytes = 4 | +| allocators.cpp:135:3:135:26 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:135:3:135:26 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:136:3:136:26 | call to operator new[] | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:136:3:136:26 | new[] | getSizeBytes = 8, requiresDealloc | | allocators.cpp:142:13:142:27 | new[] | getSizeExpr = x, getSizeMult = 10, requiresDealloc | | allocators.cpp:143:13:143:28 | new[] | getSizeBytes = 400, requiresDealloc | | allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc | +| allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc | deallocationFunctions deallocationExprs | allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 | From 254c877d0a77253fcd0228528dd9b53fb27addad Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 10:32:22 +0100 Subject: [PATCH 205/459] C++: Deduplicate AllocationExprs. --- .../semmle/code/cpp/models/implementations/Allocation.qll | 3 +++ cpp/ql/test/library-tests/allocators/allocators.expected | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index 81b4a6c8ea6..9461213f56c 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -261,6 +261,9 @@ class CallAllocationExpr extends AllocationExpr, FunctionCall { exists(target.getReallocPtrArg()) and getArgument(target.getSizeArg()).getValue().toInt() = 0 ) + and + // these are modelled directly (and more accurately), avoid duplication + not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this) } override Expr getSizeExpr() { result = getArgument(target.getSizeArg()) } diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index 9c598181f04..405b69e30ef 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -61,17 +61,13 @@ allocationFunctions | file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc | allocationExprs | allocators.cpp:49:3:49:9 | new | getSizeBytes = 4, requiresDealloc | -| allocators.cpp:50:3:50:15 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:50:3:50:15 | new | getSizeBytes = 4, requiresDealloc | | allocators.cpp:51:3:51:11 | new | getSizeBytes = 4, requiresDealloc | | allocators.cpp:52:3:52:14 | new | getSizeBytes = 8, requiresDealloc | -| allocators.cpp:53:3:53:27 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:53:3:53:27 | new | getSizeBytes = 8, requiresDealloc | | allocators.cpp:54:3:54:17 | new | getSizeBytes = 256, requiresDealloc | -| allocators.cpp:55:3:55:25 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:55:3:55:25 | new | getSizeBytes = 256, requiresDealloc | | allocators.cpp:68:3:68:12 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | -| allocators.cpp:69:3:69:18 | call to operator new[] | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:69:3:69:18 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | | allocators.cpp:70:3:70:15 | new[] | getSizeExpr = n, getSizeMult = 8, requiresDealloc | | allocators.cpp:71:3:71:20 | new[] | getSizeExpr = n, getSizeMult = 256, requiresDealloc | @@ -80,13 +76,9 @@ allocationExprs | allocators.cpp:108:3:108:19 | new[] | getSizeExpr = n, getSizeMult = 1, requiresDealloc | | allocators.cpp:109:3:109:35 | new | getSizeBytes = 128, requiresDealloc | | allocators.cpp:110:3:110:37 | new[] | getSizeBytes = 1280, requiresDealloc | -| allocators.cpp:129:3:129:21 | call to operator new | getSizeExpr = , getSizeMult = 1 | | allocators.cpp:129:3:129:21 | new | getSizeBytes = 4 | -| allocators.cpp:132:3:132:17 | call to operator new[] | getSizeExpr = , getSizeMult = 1 | | allocators.cpp:132:3:132:17 | new[] | getSizeBytes = 4 | -| allocators.cpp:135:3:135:26 | call to operator new | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:135:3:135:26 | new | getSizeBytes = 4, requiresDealloc | -| allocators.cpp:136:3:136:26 | call to operator new[] | getSizeExpr = , getSizeMult = 1, requiresDealloc | | allocators.cpp:136:3:136:26 | new[] | getSizeBytes = 8, requiresDealloc | | allocators.cpp:142:13:142:27 | new[] | getSizeExpr = x, getSizeMult = 10, requiresDealloc | | allocators.cpp:143:13:143:28 | new[] | getSizeBytes = 400, requiresDealloc | From 3b12d1adfd3dcfeb02aa1792e99c9db028d9a333 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 09:46:21 +0100 Subject: [PATCH 206/459] C++: Test getPlacementArgument(). --- cpp/ql/test/library-tests/allocators/allocators.expected | 4 ++-- cpp/ql/test/library-tests/allocators/allocators.ql | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index 405b69e30ef..ce6a893af7f 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -51,8 +51,8 @@ allocationFunctions | allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc | | allocators.cpp:9:7:9:18 | operator new | getSizeArg = 0, requiresDealloc | | allocators.cpp:10:7:10:20 | operator new[] | getSizeArg = 0, requiresDealloc | -| allocators.cpp:121:7:121:18 | operator new | getSizeArg = 0 | -| allocators.cpp:122:7:122:20 | operator new[] | getSizeArg = 0 | +| allocators.cpp:121:7:121:18 | operator new | getPlacementArgument = 1, getSizeArg = 0 | +| allocators.cpp:122:7:122:20 | operator new[] | getPlacementArgument = 1, getSizeArg = 0 | | allocators.cpp:123:7:123:18 | operator new | getSizeArg = 0, requiresDealloc | | allocators.cpp:124:7:124:20 | operator new[] | getSizeArg = 0, requiresDealloc | | file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc | diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index a50fe4be3d4..5993bf6d390 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -1,4 +1,5 @@ import default +import semmle.code.cpp.models.implementations.Allocation query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form, string placement) { exists(Function allocator, Type allocatedType | @@ -115,6 +116,8 @@ string describeAllocationFunction(AllocationFunction f) { f.requiresDealloc() and result = "requiresDealloc" ) + or + result = "getPlacementArgument = " + f.(OperatorNewAllocationFunction).getPlacementArgument().toString() } query predicate allocationFunctions(AllocationFunction f, string descr) { From 3784b180d82d99c7ed26f3835267f8c7927ce564 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 31 Mar 2020 12:07:55 +0200 Subject: [PATCH 207/459] changes based on review --- .../ql/src/Declarations/DeadStoreOfLocal.ql | 23 ++++--------------- .../DeadStoreOfLocal.expected | 14 +++++------ 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql index 9406d5c5c61..9d5a7338a9b 100644 --- a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql +++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql @@ -29,23 +29,6 @@ predicate deadStoreOfLocal(VarDef vd, PurelyLocalVariable v) { not exists(SsaExplicitDefinition ssa | ssa.defines(vd, v)) } -/** - * Holds if there exists another definition of the variable `v` that dominates `dead`. - */ -predicate hasDominatingDef(VarDef dead, PurelyLocalVariable v) { - exists(VarDef otherDef | not otherDef = dead and otherDef.getAVariable() = v | - dead.getBasicBlock().getASuccessor+() = otherDef.getBasicBlock() - or - exists(ReachableBasicBlock bb, int i, int j | - bb = otherDef.getBasicBlock() and bb = dead.getBasicBlock() - | - bb.defAt(i, v, dead) and - bb.defAt(j, v, otherDef) and - j > i - ) - ) -} - from VarDef dead, PurelyLocalVariable v, string msg where deadStoreOfLocal(dead, v) and @@ -80,8 +63,10 @@ where ( // To avoid confusion about the meaning of "definition" and "declaration" we avoid // the term "definition" when the alert location is a variable declaration. - if dead instanceof VariableDeclarator and hasDominatingDef(dead, v) + if + dead instanceof VariableDeclarator and + not exists(SsaImplicitInit init | init.getVariable().getSourceVariable() = v) // the variable is dead at the hoisted implicit initialization. then msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten." - else msg = "This definition of " + v.getName() + " is useless, since its value is never read." + else msg = "The value assigned to " + v.getName() + " here is unused." ) select dead, msg diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected index fd87be61375..88b5fc55b25 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected @@ -1,13 +1,13 @@ -| overload.ts:10:12:10:14 | baz | This definition of baz is useless, since its value is never read. | +| overload.ts:10:12:10:14 | baz | The value assigned to baz here is unused. | | tst2.js:26:9:26:14 | x = 23 | The initial value of x is unused, since it is always overwritten. | -| tst2.js:28:9:28:14 | x = 42 | This definition of x is useless, since its value is never read. | -| tst3.js:2:1:2:36 | exports ... a: 23 } | This definition of exports is useless, since its value is never read. | -| tst3b.js:2:18:2:36 | exports = { a: 23 } | This definition of exports is useless, since its value is never read. | -| tst.js:6:2:6:7 | y = 23 | This definition of y is useless, since its value is never read. | +| tst2.js:28:9:28:14 | x = 42 | The value assigned to x here is unused. | +| tst3.js:2:1:2:36 | exports ... a: 23 } | The value assigned to exports here is unused. | +| tst3b.js:2:18:2:36 | exports = { a: 23 } | The value assigned to exports here is unused. | +| tst.js:6:2:6:7 | y = 23 | The value assigned to y here is unused. | | tst.js:13:6:13:11 | a = 23 | The initial value of a is unused, since it is always overwritten. | -| tst.js:13:14:13:19 | a = 42 | This definition of a is useless, since its value is never read. | +| tst.js:13:14:13:19 | a = 42 | The value assigned to a here is unused. | | tst.js:45:6:45:11 | x = 23 | The initial value of x is unused, since it is always overwritten. | | tst.js:51:6:51:11 | x = 23 | The initial value of x is unused, since it is always overwritten. | | tst.js:132:7:132:13 | {x} = o | The initial value of x is unused, since it is always overwritten. | | tst.js:162:6:162:14 | [x] = [0] | The initial value of x is unused, since it is always overwritten. | -| tst.js:172:7:172:17 | nSign = foo | This definition of nSign is useless, since its value is never read. | +| tst.js:172:7:172:17 | nSign = foo | The value assigned to nSign here is unused. | From 688464a00f4498c8952d54a329ebf05050376449 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 31 Mar 2020 12:22:07 +0200 Subject: [PATCH 208/459] C++: Add testcases with new and accept output --- .../dataflow/security-taint/tainted.expected | 15 ++ .../security-taint/tainted_diff.expected | 9 ++ .../security-taint/tainted_ir.expected | 6 + .../dataflow/security-taint/test.cpp | 13 ++ .../ir/ssa/aliased_ssa_ir.expected | 131 ++++++++++++++++++ .../ir/ssa/aliased_ssa_ir_unsound.expected | 131 ++++++++++++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 15 ++ .../ir/ssa/unaliased_ssa_ir.expected | 115 +++++++++++++++ .../ir/ssa/unaliased_ssa_ir_unsound.expected | 115 +++++++++++++++ 9 files changed, 550 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected index f4a9288036d..cdea135e301 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected @@ -73,3 +73,18 @@ | test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | | | test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:20:11:21 | s1 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:36:11:37 | s2 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:17:106:24 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:33 | call to getenv | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:46 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:108:8:108:11 | copy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:2:109:7 | call to strcpy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:9:109:12 | copy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:15:109:22 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy | | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected index 8cc64a4c9bc..d89a1de6c86 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected @@ -14,3 +14,12 @@ | test.cpp:100:12:100:15 | call to gets | test.cpp:100:2:100:8 | pointer | AST only | | test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | AST only | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | IR only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:108:8:108:11 | copy | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:9:109:12 | copy | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected index c8cca156177..bed6881cc5f 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected @@ -57,3 +57,9 @@ | test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:36:11:37 | s2 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:17:106:24 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:33 | call to getenv | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:46 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:2:109:7 | call to strcpy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:15:109:22 | userName | | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp b/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp index 5feea7d1e7b..f25f9eeb697 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp @@ -99,3 +99,16 @@ void test_gets() pointer = gets(buffer); } + +const char *alias_global_new; + +void newBuffer() { + const char *userName = getenv("USER_NAME"); + char *alias = new char[4096]; + char *copy = new char[4096]; + strcpy(copy, userName); + alias_global_new = alias; // to force a Chi node on all aliased memory + if (!strcmp(copy, "admin")) { // copy should be tainted + isAdmin = true; + } +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index e271e7bfff3..76417701a35 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -1345,3 +1345,134 @@ ssa.cpp: # 275| v275_13(void) = UnmodeledUse : mu* # 275| v275_14(void) = AliasedUse : ~m281_2 # 275| v275_15(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| m286_2(unknown) = AliasedDefinition : +# 286| m286_3(unknown) = InitializeNonLocal : +# 286| m286_4(unknown) = Chi : total:m286_2, partial:m286_3 +# 286| mu286_5(unknown) = UnmodeledDefinition : +# 286| r286_6(glval) = InitializeThis : +# 286| r286_7(glval) = VariableAddress[x] : +# 286| m286_8(int) = InitializeParameter[x] : &:r286_7 +# 286| v286_9(void) = NoOp : +# 286| v286_10(void) = ReturnVoid : +# 286| v286_11(void) = UnmodeledUse : mu* +# 286| v286_12(void) = AliasedUse : m286_3 +# 286| v286_13(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| m287_2(unknown) = AliasedDefinition : +# 287| m287_3(unknown) = InitializeNonLocal : +# 287| m287_4(unknown) = Chi : total:m287_2, partial:m287_3 +# 287| mu287_5(unknown) = UnmodeledDefinition : +# 287| r287_6(glval) = InitializeThis : +# 287| r287_7(glval) = VariableAddress[p#0] : +# 287| m287_8(A *) = InitializeParameter[p#0] : &:r287_7 +# 287| r287_9(A *) = Load : &:r287_7, m287_8 +# 287| m287_10(unknown) = InitializeIndirection[p#0] : &:r287_9 +# 287| v287_11(void) = NoOp : +# 287| v287_12(void) = ReturnIndirection : &:r287_9, m287_10 +# 287| v287_13(void) = ReturnVoid : +# 287| v287_14(void) = UnmodeledUse : mu* +# 287| v287_15(void) = AliasedUse : m287_3 +# 287| v287_16(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| m288_2(unknown) = AliasedDefinition : +# 288| m288_3(unknown) = InitializeNonLocal : +# 288| m288_4(unknown) = Chi : total:m288_2, partial:m288_3 +# 288| mu288_5(unknown) = UnmodeledDefinition : +# 288| r288_6(glval) = InitializeThis : +# 288| v288_7(void) = NoOp : +# 288| v288_8(void) = ReturnVoid : +# 288| v288_9(void) = UnmodeledUse : mu* +# 288| v288_10(void) = AliasedUse : m288_3 +# 288| v288_11(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| m291_2(unknown) = AliasedDefinition : +# 291| m291_3(unknown) = InitializeNonLocal : +# 291| m291_4(unknown) = Chi : total:m291_2, partial:m291_3 +# 291| mu291_5(unknown) = UnmodeledDefinition : +# 291| r291_6(glval) = VariableAddress[x] : +# 291| m291_7(int) = InitializeParameter[x] : &:r291_6 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| m292_5(unknown) = ^CallSideEffect : ~m291_4 +# 292| m292_6(unknown) = Chi : total:m291_4, partial:m292_5 +# 292| r292_7(Point *) = Convert : r292_4 +# 292| m292_8(Point *) = Store : &:r292_1, r292_7 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| m293_5(unknown) = ^CallSideEffect : ~m292_6 +# 293| m293_6(unknown) = Chi : total:m292_6, partial:m293_5 +# 293| r293_7(Point *) = Convert : r293_4 +# 293| m293_8(Point *) = Store : &:r293_1, r293_7 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| m294_5(unknown) = ^CallSideEffect : ~m293_6 +# 294| m294_6(unknown) = Chi : total:m293_6, partial:m294_5 +# 294| r294_7(A *) = Convert : r294_4 +# 294| r294_8(glval) = FunctionAddress[A] : +# 294| r294_9(glval) = FunctionAddress[operator new] : +# 294| r294_10(unsigned long) = Constant[4] : +# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 +# 294| m294_12(unknown) = ^CallSideEffect : ~m294_6 +# 294| m294_13(unknown) = Chi : total:m294_6, partial:m294_12 +# 294| r294_14(A *) = Convert : r294_11 +# 294| r294_15(glval) = FunctionAddress[A] : +# 294| r294_16(glval) = VariableAddress[x] : +# 294| r294_17(int) = Load : &:r294_16, m291_7 +# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 +# 294| m294_19(unknown) = ^CallSideEffect : ~m294_13 +# 294| m294_20(unknown) = Chi : total:m294_13, partial:m294_19 +# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 +# 294| m294_22(unknown) = Chi : total:m294_20, partial:m294_21 +# 294| v294_23(void) = Call : func:r294_8, this:r294_7, 0:r294_14 +# 294| m294_24(unknown) = ^CallSideEffect : ~m294_22 +# 294| m294_25(unknown) = Chi : total:m294_22, partial:m294_24 +# 294| m294_26(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 +# 294| m294_27(unknown) = Chi : total:m294_25, partial:m294_26 +# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_14, ~m294_27 +# 294| m294_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 +# 294| m294_30(unknown) = Chi : total:m294_27, partial:m294_29 +# 294| r294_31(glval) = FieldAddress[i] : r294_7 +# 294| r294_32(int) = Load : &:r294_31, ~m294_30 +# 294| m294_33(int) = Store : &:r294_1, r294_32 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_30 +# 295| m295_6(unknown) = Chi : total:m294_30, partial:m295_5 +# 295| r295_7(A *) = Convert : r295_4 +# 295| r295_8(glval) = FunctionAddress[A] : +# 295| v295_9(void) = Call : func:r295_8, this:r295_7 +# 295| m295_10(unknown) = ^CallSideEffect : ~m295_6 +# 295| m295_11(unknown) = Chi : total:m295_6, partial:m295_10 +# 295| m295_12(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 +# 295| m295_13(unknown) = Chi : total:m295_11, partial:m295_12 +# 295| m295_14(A *) = Store : &:r295_1, r295_7 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_8 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_8(glval) = VariableAddress[#return] : +# 291| v291_9(void) = ReturnValue : &:r291_8, m296_4 +# 291| v291_10(void) = UnmodeledUse : mu* +# 291| v291_11(void) = AliasedUse : ~m295_13 +# 291| v291_12(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index 0566e36756b..3ee4d83a719 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1334,3 +1334,134 @@ ssa.cpp: # 275| v275_13(void) = UnmodeledUse : mu* # 275| v275_14(void) = AliasedUse : ~m277_5 # 275| v275_15(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| m286_2(unknown) = AliasedDefinition : +# 286| m286_3(unknown) = InitializeNonLocal : +# 286| m286_4(unknown) = Chi : total:m286_2, partial:m286_3 +# 286| mu286_5(unknown) = UnmodeledDefinition : +# 286| r286_6(glval) = InitializeThis : +# 286| r286_7(glval) = VariableAddress[x] : +# 286| m286_8(int) = InitializeParameter[x] : &:r286_7 +# 286| v286_9(void) = NoOp : +# 286| v286_10(void) = ReturnVoid : +# 286| v286_11(void) = UnmodeledUse : mu* +# 286| v286_12(void) = AliasedUse : m286_3 +# 286| v286_13(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| m287_2(unknown) = AliasedDefinition : +# 287| m287_3(unknown) = InitializeNonLocal : +# 287| m287_4(unknown) = Chi : total:m287_2, partial:m287_3 +# 287| mu287_5(unknown) = UnmodeledDefinition : +# 287| r287_6(glval) = InitializeThis : +# 287| r287_7(glval) = VariableAddress[p#0] : +# 287| m287_8(A *) = InitializeParameter[p#0] : &:r287_7 +# 287| r287_9(A *) = Load : &:r287_7, m287_8 +# 287| m287_10(unknown) = InitializeIndirection[p#0] : &:r287_9 +# 287| v287_11(void) = NoOp : +# 287| v287_12(void) = ReturnIndirection : &:r287_9, m287_10 +# 287| v287_13(void) = ReturnVoid : +# 287| v287_14(void) = UnmodeledUse : mu* +# 287| v287_15(void) = AliasedUse : m287_3 +# 287| v287_16(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| m288_2(unknown) = AliasedDefinition : +# 288| m288_3(unknown) = InitializeNonLocal : +# 288| m288_4(unknown) = Chi : total:m288_2, partial:m288_3 +# 288| mu288_5(unknown) = UnmodeledDefinition : +# 288| r288_6(glval) = InitializeThis : +# 288| v288_7(void) = NoOp : +# 288| v288_8(void) = ReturnVoid : +# 288| v288_9(void) = UnmodeledUse : mu* +# 288| v288_10(void) = AliasedUse : m288_3 +# 288| v288_11(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| m291_2(unknown) = AliasedDefinition : +# 291| m291_3(unknown) = InitializeNonLocal : +# 291| m291_4(unknown) = Chi : total:m291_2, partial:m291_3 +# 291| mu291_5(unknown) = UnmodeledDefinition : +# 291| r291_6(glval) = VariableAddress[x] : +# 291| m291_7(int) = InitializeParameter[x] : &:r291_6 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| m292_5(unknown) = ^CallSideEffect : ~m291_4 +# 292| m292_6(unknown) = Chi : total:m291_4, partial:m292_5 +# 292| r292_7(Point *) = Convert : r292_4 +# 292| m292_8(Point *) = Store : &:r292_1, r292_7 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| m293_5(unknown) = ^CallSideEffect : ~m292_6 +# 293| m293_6(unknown) = Chi : total:m292_6, partial:m293_5 +# 293| r293_7(Point *) = Convert : r293_4 +# 293| m293_8(Point *) = Store : &:r293_1, r293_7 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| m294_5(unknown) = ^CallSideEffect : ~m293_6 +# 294| m294_6(unknown) = Chi : total:m293_6, partial:m294_5 +# 294| r294_7(A *) = Convert : r294_4 +# 294| r294_8(glval) = FunctionAddress[A] : +# 294| r294_9(glval) = FunctionAddress[operator new] : +# 294| r294_10(unsigned long) = Constant[4] : +# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 +# 294| m294_12(unknown) = ^CallSideEffect : ~m294_6 +# 294| m294_13(unknown) = Chi : total:m294_6, partial:m294_12 +# 294| r294_14(A *) = Convert : r294_11 +# 294| r294_15(glval) = FunctionAddress[A] : +# 294| r294_16(glval) = VariableAddress[x] : +# 294| r294_17(int) = Load : &:r294_16, m291_7 +# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 +# 294| m294_19(unknown) = ^CallSideEffect : ~m294_13 +# 294| m294_20(unknown) = Chi : total:m294_13, partial:m294_19 +# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 +# 294| m294_22(unknown) = Chi : total:m294_20, partial:m294_21 +# 294| v294_23(void) = Call : func:r294_8, this:r294_7, 0:r294_14 +# 294| m294_24(unknown) = ^CallSideEffect : ~m294_22 +# 294| m294_25(unknown) = Chi : total:m294_22, partial:m294_24 +# 294| m294_26(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 +# 294| m294_27(unknown) = Chi : total:m294_25, partial:m294_26 +# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_14, ~m294_27 +# 294| m294_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 +# 294| m294_30(unknown) = Chi : total:m294_27, partial:m294_29 +# 294| r294_31(glval) = FieldAddress[i] : r294_7 +# 294| r294_32(int) = Load : &:r294_31, ~m294_30 +# 294| m294_33(int) = Store : &:r294_1, r294_32 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_30 +# 295| m295_6(unknown) = Chi : total:m294_30, partial:m295_5 +# 295| r295_7(A *) = Convert : r295_4 +# 295| r295_8(glval) = FunctionAddress[A] : +# 295| v295_9(void) = Call : func:r295_8, this:r295_7 +# 295| m295_10(unknown) = ^CallSideEffect : ~m295_6 +# 295| m295_11(unknown) = Chi : total:m295_6, partial:m295_10 +# 295| m295_12(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 +# 295| m295_13(unknown) = Chi : total:m295_11, partial:m295_12 +# 295| m295_14(A *) = Store : &:r295_1, r295_7 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_8 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_8(glval) = VariableAddress[#return] : +# 291| v291_9(void) = ReturnValue : &:r291_8, m296_4 +# 291| v291_10(void) = UnmodeledUse : mu* +# 291| v291_11(void) = AliasedUse : ~m295_13 +# 291| v291_12(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index f7e75596468..6c5fd5eaf87 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -280,3 +280,18 @@ void EscapedButNotConflated(bool c, Point p, int x1) { } int x = a.x; // The phi node here is not conflated } + +struct A { + int i; + A(int x) {} + A(A*) {} + A() {} +}; + +Point *NewAliasing(int x) { + Point* p = new Point; + Point* q = new Point; + int j = new A(new A(x))->i; + A* a = new A; + return p; +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 11e502f54f1..3627c6493f3 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -1238,3 +1238,118 @@ ssa.cpp: # 275| v275_12(void) = UnmodeledUse : mu* # 275| v275_13(void) = AliasedUse : ~mu275_4 # 275| v275_14(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| mu286_2(unknown) = AliasedDefinition : +# 286| mu286_3(unknown) = InitializeNonLocal : +# 286| mu286_4(unknown) = UnmodeledDefinition : +# 286| r286_5(glval) = InitializeThis : +# 286| r286_6(glval) = VariableAddress[x] : +# 286| m286_7(int) = InitializeParameter[x] : &:r286_6 +# 286| v286_8(void) = NoOp : +# 286| v286_9(void) = ReturnVoid : +# 286| v286_10(void) = UnmodeledUse : mu* +# 286| v286_11(void) = AliasedUse : ~mu286_4 +# 286| v286_12(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| mu287_2(unknown) = AliasedDefinition : +# 287| mu287_3(unknown) = InitializeNonLocal : +# 287| mu287_4(unknown) = UnmodeledDefinition : +# 287| r287_5(glval) = InitializeThis : +# 287| r287_6(glval) = VariableAddress[p#0] : +# 287| m287_7(A *) = InitializeParameter[p#0] : &:r287_6 +# 287| r287_8(A *) = Load : &:r287_6, m287_7 +# 287| mu287_9(unknown) = InitializeIndirection[p#0] : &:r287_8 +# 287| v287_10(void) = NoOp : +# 287| v287_11(void) = ReturnIndirection : &:r287_8, ~mu287_4 +# 287| v287_12(void) = ReturnVoid : +# 287| v287_13(void) = UnmodeledUse : mu* +# 287| v287_14(void) = AliasedUse : ~mu287_4 +# 287| v287_15(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| mu288_2(unknown) = AliasedDefinition : +# 288| mu288_3(unknown) = InitializeNonLocal : +# 288| mu288_4(unknown) = UnmodeledDefinition : +# 288| r288_5(glval) = InitializeThis : +# 288| v288_6(void) = NoOp : +# 288| v288_7(void) = ReturnVoid : +# 288| v288_8(void) = UnmodeledUse : mu* +# 288| v288_9(void) = AliasedUse : ~mu288_4 +# 288| v288_10(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| mu291_2(unknown) = AliasedDefinition : +# 291| mu291_3(unknown) = InitializeNonLocal : +# 291| mu291_4(unknown) = UnmodeledDefinition : +# 291| r291_5(glval) = VariableAddress[x] : +# 291| m291_6(int) = InitializeParameter[x] : &:r291_5 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| mu292_5(unknown) = ^CallSideEffect : ~mu291_4 +# 292| r292_6(Point *) = Convert : r292_4 +# 292| m292_7(Point *) = Store : &:r292_1, r292_6 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| mu293_5(unknown) = ^CallSideEffect : ~mu291_4 +# 293| r293_6(Point *) = Convert : r293_4 +# 293| m293_7(Point *) = Store : &:r293_1, r293_6 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| mu294_5(unknown) = ^CallSideEffect : ~mu291_4 +# 294| r294_6(A *) = Convert : r294_4 +# 294| r294_7(glval) = FunctionAddress[A] : +# 294| r294_8(glval) = FunctionAddress[operator new] : +# 294| r294_9(unsigned long) = Constant[4] : +# 294| r294_10(void *) = Call : func:r294_8, 0:r294_9 +# 294| mu294_11(unknown) = ^CallSideEffect : ~mu291_4 +# 294| r294_12(A *) = Convert : r294_10 +# 294| r294_13(glval) = FunctionAddress[A] : +# 294| r294_14(glval) = VariableAddress[x] : +# 294| r294_15(int) = Load : &:r294_14, m291_6 +# 294| v294_16(void) = Call : func:r294_13, this:r294_12, 0:r294_15 +# 294| mu294_17(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_18(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_12 +# 294| v294_19(void) = Call : func:r294_7, this:r294_6, 0:r294_12 +# 294| mu294_20(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_6 +# 294| v294_22(void) = ^BufferReadSideEffect[0] : &:r294_12, ~mu291_4 +# 294| mu294_23(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_12 +# 294| r294_24(glval) = FieldAddress[i] : r294_6 +# 294| r294_25(int) = Load : &:r294_24, ~mu291_4 +# 294| m294_26(int) = Store : &:r294_1, r294_25 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| mu295_5(unknown) = ^CallSideEffect : ~mu291_4 +# 295| r295_6(A *) = Convert : r295_4 +# 295| r295_7(glval) = FunctionAddress[A] : +# 295| v295_8(void) = Call : func:r295_7, this:r295_6 +# 295| mu295_9(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_10(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_6 +# 295| m295_11(A *) = Store : &:r295_1, r295_6 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_7 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_7(glval) = VariableAddress[#return] : +# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 +# 291| v291_9(void) = UnmodeledUse : mu* +# 291| v291_10(void) = AliasedUse : ~mu291_4 +# 291| v291_11(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index 11e502f54f1..3627c6493f3 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -1238,3 +1238,118 @@ ssa.cpp: # 275| v275_12(void) = UnmodeledUse : mu* # 275| v275_13(void) = AliasedUse : ~mu275_4 # 275| v275_14(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| mu286_2(unknown) = AliasedDefinition : +# 286| mu286_3(unknown) = InitializeNonLocal : +# 286| mu286_4(unknown) = UnmodeledDefinition : +# 286| r286_5(glval) = InitializeThis : +# 286| r286_6(glval) = VariableAddress[x] : +# 286| m286_7(int) = InitializeParameter[x] : &:r286_6 +# 286| v286_8(void) = NoOp : +# 286| v286_9(void) = ReturnVoid : +# 286| v286_10(void) = UnmodeledUse : mu* +# 286| v286_11(void) = AliasedUse : ~mu286_4 +# 286| v286_12(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| mu287_2(unknown) = AliasedDefinition : +# 287| mu287_3(unknown) = InitializeNonLocal : +# 287| mu287_4(unknown) = UnmodeledDefinition : +# 287| r287_5(glval) = InitializeThis : +# 287| r287_6(glval) = VariableAddress[p#0] : +# 287| m287_7(A *) = InitializeParameter[p#0] : &:r287_6 +# 287| r287_8(A *) = Load : &:r287_6, m287_7 +# 287| mu287_9(unknown) = InitializeIndirection[p#0] : &:r287_8 +# 287| v287_10(void) = NoOp : +# 287| v287_11(void) = ReturnIndirection : &:r287_8, ~mu287_4 +# 287| v287_12(void) = ReturnVoid : +# 287| v287_13(void) = UnmodeledUse : mu* +# 287| v287_14(void) = AliasedUse : ~mu287_4 +# 287| v287_15(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| mu288_2(unknown) = AliasedDefinition : +# 288| mu288_3(unknown) = InitializeNonLocal : +# 288| mu288_4(unknown) = UnmodeledDefinition : +# 288| r288_5(glval) = InitializeThis : +# 288| v288_6(void) = NoOp : +# 288| v288_7(void) = ReturnVoid : +# 288| v288_8(void) = UnmodeledUse : mu* +# 288| v288_9(void) = AliasedUse : ~mu288_4 +# 288| v288_10(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| mu291_2(unknown) = AliasedDefinition : +# 291| mu291_3(unknown) = InitializeNonLocal : +# 291| mu291_4(unknown) = UnmodeledDefinition : +# 291| r291_5(glval) = VariableAddress[x] : +# 291| m291_6(int) = InitializeParameter[x] : &:r291_5 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| mu292_5(unknown) = ^CallSideEffect : ~mu291_4 +# 292| r292_6(Point *) = Convert : r292_4 +# 292| m292_7(Point *) = Store : &:r292_1, r292_6 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| mu293_5(unknown) = ^CallSideEffect : ~mu291_4 +# 293| r293_6(Point *) = Convert : r293_4 +# 293| m293_7(Point *) = Store : &:r293_1, r293_6 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| mu294_5(unknown) = ^CallSideEffect : ~mu291_4 +# 294| r294_6(A *) = Convert : r294_4 +# 294| r294_7(glval) = FunctionAddress[A] : +# 294| r294_8(glval) = FunctionAddress[operator new] : +# 294| r294_9(unsigned long) = Constant[4] : +# 294| r294_10(void *) = Call : func:r294_8, 0:r294_9 +# 294| mu294_11(unknown) = ^CallSideEffect : ~mu291_4 +# 294| r294_12(A *) = Convert : r294_10 +# 294| r294_13(glval) = FunctionAddress[A] : +# 294| r294_14(glval) = VariableAddress[x] : +# 294| r294_15(int) = Load : &:r294_14, m291_6 +# 294| v294_16(void) = Call : func:r294_13, this:r294_12, 0:r294_15 +# 294| mu294_17(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_18(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_12 +# 294| v294_19(void) = Call : func:r294_7, this:r294_6, 0:r294_12 +# 294| mu294_20(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_6 +# 294| v294_22(void) = ^BufferReadSideEffect[0] : &:r294_12, ~mu291_4 +# 294| mu294_23(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_12 +# 294| r294_24(glval) = FieldAddress[i] : r294_6 +# 294| r294_25(int) = Load : &:r294_24, ~mu291_4 +# 294| m294_26(int) = Store : &:r294_1, r294_25 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| mu295_5(unknown) = ^CallSideEffect : ~mu291_4 +# 295| r295_6(A *) = Convert : r295_4 +# 295| r295_7(glval) = FunctionAddress[A] : +# 295| v295_8(void) = Call : func:r295_7, this:r295_6 +# 295| mu295_9(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_10(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_6 +# 295| m295_11(A *) = Store : &:r295_1, r295_6 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_7 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_7(glval) = VariableAddress[#return] : +# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 +# 291| v291_9(void) = UnmodeledUse : mu* +# 291| v291_10(void) = AliasedUse : ~mu291_4 +# 291| v291_11(void) = ExitFunction : From a0158b3917937bc7ad55533d0a661f2a5e6989fe Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Tue, 31 Mar 2020 11:31:41 +0100 Subject: [PATCH 209/459] Update intros in QL handbook --- docs/language/ql-handbook/aliases.rst | 5 +++-- docs/language/ql-handbook/annotations.rst | 1 + docs/language/ql-handbook/evaluation.rst | 2 ++ docs/language/ql-handbook/expressions.rst | 7 +++---- docs/language/ql-handbook/formulas.rst | 5 ++--- docs/language/ql-handbook/lexical-syntax.rst | 6 +++--- docs/language/ql-handbook/name-resolution.rst | 2 ++ docs/language/ql-handbook/queries.rst | 5 +++-- docs/language/ql-handbook/types.rst | 4 +++- docs/language/ql-handbook/variables.rst | 4 ++-- docs/language/ql-spec/language.rst | 6 +++--- 11 files changed, 27 insertions(+), 20 deletions(-) diff --git a/docs/language/ql-handbook/aliases.rst b/docs/language/ql-handbook/aliases.rst index 88675370081..03bdc835a30 100644 --- a/docs/language/ql-handbook/aliases.rst +++ b/docs/language/ql-handbook/aliases.rst @@ -4,8 +4,9 @@ Aliases ####### -An alias is an alternative name for an existing QL entity. Once you've defined an alias, -you can use that new name to refer to the entity in the current module's :ref:`namespace `. +An alias is an alternative name for an existing QL entity. + +Once you've defined an alias, you can use that new name to refer to the entity in the current module's :ref:`namespace `. Defining an alias ***************** diff --git a/docs/language/ql-handbook/annotations.rst b/docs/language/ql-handbook/annotations.rst index 8673b8194f6..816b5ea5310 100644 --- a/docs/language/ql-handbook/annotations.rst +++ b/docs/language/ql-handbook/annotations.rst @@ -4,6 +4,7 @@ Annotations ########### An annotation is a string that you can place directly before the declaration of a QL entity or name. + For example, to declare a module ``M`` as private, you could use:: private module M { diff --git a/docs/language/ql-handbook/evaluation.rst b/docs/language/ql-handbook/evaluation.rst index 251b951c0e1..42520f634a2 100644 --- a/docs/language/ql-handbook/evaluation.rst +++ b/docs/language/ql-handbook/evaluation.rst @@ -3,6 +3,8 @@ Evaluation of QL programs ######################### +A QL program is evaluated in a number of different steps. + Process ******* diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index 27e8543e4f5..dffd6a83ee1 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -3,11 +3,10 @@ Expressions ########### -An expression evaluates to a set of values in QL. For example, the expression ``1 + 2`` -evaluates to the integer ``3`` and the expression ``"QL"`` evaluates to the string ``"QL"``. +An expression evaluates to a set of values and has a type. -A valid expression also has a :ref:`type `. -In the above examples, ``1 + 2`` has type ``int`` and ``"QL"`` has type ``string``. +For example, the expression ``1 + 2`` +evaluates to the integer ``3`` and the expression ``"QL"`` evaluates to the string ``"QL"``. ``1 + 2`` has :ref:`type ` ``int`` and ``"QL"`` has type ``string``. The following sections describe the expressions that are available in QL. diff --git a/docs/language/ql-handbook/formulas.rst b/docs/language/ql-handbook/formulas.rst index 45ef1302fb7..cedbfa4a4cf 100644 --- a/docs/language/ql-handbook/formulas.rst +++ b/docs/language/ql-handbook/formulas.rst @@ -3,10 +3,9 @@ Formulas ######## -Formulas define logical relations between the :ref:`free variables ` used in -:ref:`expressions `. +Formulas define logical relations between the free variables used in expressions. -Depending on the values assigned to those free variables, a formula can be true or false. +Depending on the values assigned to those :ref:`free variables `, a formula can be true or false. When a formula is true, we often say that the formula *holds*. For example, the formula ``x = 4 + 5`` holds if the value ``9`` is assigned to ``x``, but it doesn't hold for other assignments to ``x``. diff --git a/docs/language/ql-handbook/lexical-syntax.rst b/docs/language/ql-handbook/lexical-syntax.rst index e25f5d266fa..481b0bf87ea 100644 --- a/docs/language/ql-handbook/lexical-syntax.rst +++ b/docs/language/ql-handbook/lexical-syntax.rst @@ -3,10 +3,10 @@ Lexical syntax ############## +The QL syntax includes different kinds of keywords, identifiers, and comments. + For an overview of the lexical syntax, see `Lexical syntax -`_ -in the QL language specification. In particular, you can find the list of QL keywords, the -different kinds of identifiers, and a description of comments. +`_ in the QL language specification. .. index:: comment, QLDoc .. _comments: diff --git a/docs/language/ql-handbook/name-resolution.rst b/docs/language/ql-handbook/name-resolution.rst index 430e80173f0..3e44140640e 100644 --- a/docs/language/ql-handbook/name-resolution.rst +++ b/docs/language/ql-handbook/name-resolution.rst @@ -3,6 +3,8 @@ Name resolution ############### +The QL compiler resolves names to program elements. + As in other programming languages, there is a distinction between the names used in QL code, and the underlying QL entities they refer to. diff --git a/docs/language/ql-handbook/queries.rst b/docs/language/ql-handbook/queries.rst index 1c21482af35..f5e10698007 100644 --- a/docs/language/ql-handbook/queries.rst +++ b/docs/language/ql-handbook/queries.rst @@ -4,8 +4,7 @@ Queries ####### -Queries are the output of a QL program: they evaluate to sets of results. Indeed, we -often refer to the whole QL program as a *query*. +Queries are the output of a QL program. they evaluate to sets of results. There are two kinds of queries. For a given :ref:`query module `, the queries in that module are: - The :ref:`select clause `, if any, defined in that module. @@ -13,6 +12,8 @@ There are two kinds of queries. For a given :ref:`query module `, :ref:`namespace `. That is, they can be defined in the module itself, or imported from a different module. +We often also refer to the whole QL program as a query. + .. index:: from, where, select .. _select-clauses: diff --git a/docs/language/ql-handbook/types.rst b/docs/language/ql-handbook/types.rst index dfa7a8cd30f..92ac01bd42b 100644 --- a/docs/language/ql-handbook/types.rst +++ b/docs/language/ql-handbook/types.rst @@ -5,7 +5,9 @@ Types ##### -QL is a statically typed language, so each variable must have a declared **type**. A type is a set of values. +QL is a statically typed language, so each variable must have a declared type. + +A type is a set of values. For example, the type ``int`` is the set of integers. Note that a value can belong to more than one of these sets, which means that it can have more than one type. diff --git a/docs/language/ql-handbook/variables.rst b/docs/language/ql-handbook/variables.rst index 25b4fff1ad2..a74d492b61c 100644 --- a/docs/language/ql-handbook/variables.rst +++ b/docs/language/ql-handbook/variables.rst @@ -5,11 +5,11 @@ Variables ######### Variables in QL are used in a similar way to variables in algebra or logic. They represent sets -of values, and those values are usually restricted by a :ref:`formula `. +of values, and those values are usually restricted by a formula. This is different from variables in some other programming languages, where variables represent memory locations that may contain data. That data can also change over time. For example, in -QL, ``n = n + 1`` is an equality formula that holds only +QL, ``n = n + 1`` is an equality :ref:`formula ` that holds only if ``n`` is equal to ``n + 1`` (so in fact it does not hold for any numeric value). In Java, ``n = n + 1`` is not an equality, but an assignment that changes the value of ``n`` by adding ``1`` to the current value. diff --git a/docs/language/ql-spec/language.rst b/docs/language/ql-spec/language.rst index eb434ef071f..12298a36b75 100644 --- a/docs/language/ql-spec/language.rst +++ b/docs/language/ql-spec/language.rst @@ -1,12 +1,12 @@ QL language specification ========================= +This is a formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. + Introduction ------------ -This document specifies the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. - -QL is a query language for Semmle databases. The data is relational: named relations hold sets of tuples. The query language is a dialect of Datalog, using stratified semantics, and it includes object-oriented classes. +QL is a query language for CodeQL databases. The data is relational: named relations hold sets of tuples. The query language is a dialect of Datalog, using stratified semantics, and it includes object-oriented classes. Notation -------- From 5bf0a087d012f16e785c53dd2f068b305d35421e Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Tue, 31 Mar 2020 12:25:23 +0100 Subject: [PATCH 210/459] Update docs/language/ql-handbook/queries.rst Co-Authored-By: James Fletcher <42464962+jf205@users.noreply.github.com> --- docs/language/ql-handbook/queries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-handbook/queries.rst b/docs/language/ql-handbook/queries.rst index f5e10698007..c6ef62d6b13 100644 --- a/docs/language/ql-handbook/queries.rst +++ b/docs/language/ql-handbook/queries.rst @@ -4,7 +4,7 @@ Queries ####### -Queries are the output of a QL program. they evaluate to sets of results. +Queries are the output of a QL program. They evaluate to sets of results. There are two kinds of queries. For a given :ref:`query module `, the queries in that module are: - The :ref:`select clause `, if any, defined in that module. From 45797dc729229c735604722c701e4c5947af88d2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 31 Mar 2020 13:53:00 +0200 Subject: [PATCH 211/459] autoformat --- javascript/ql/src/Declarations/DeadStoreOfLocal.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql index 9d5a7338a9b..1002ac0a4e3 100644 --- a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql +++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql @@ -65,7 +65,7 @@ where // the term "definition" when the alert location is a variable declaration. if dead instanceof VariableDeclarator and - not exists(SsaImplicitInit init | init.getVariable().getSourceVariable() = v) // the variable is dead at the hoisted implicit initialization. + not exists(SsaImplicitInit init | init.getVariable().getSourceVariable() = v) // the variable is dead at the hoisted implicit initialization. then msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten." else msg = "The value assigned to " + v.getName() + " here is unused." ) From 18e60fabaf45bde94c8ca78c6f547a03080e0e4a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 10:19:50 +0100 Subject: [PATCH 212/459] C++: Model operator delete and operator delete[]. --- .../models/implementations/Deallocation.qll | 21 +++++++++++++++++++ .../allocators/allocators.expected | 10 +++++++++ 2 files changed, 31 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 83309855e18..c3b4cdd6584 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -79,6 +79,27 @@ class StandardDeallocationFunction extends DeallocationFunction { override int getFreedArg() { result = freedArg } } +/** + * An `operator delete` or `operator delete[]` function that may be associated + * with a `delete` or `delete[]` expression. Note that `delete` and `delete[]` + * are not function calls, but these functions may also be called directly. + */ +class OperatorDeleteDeallocationFunction extends DeallocationFunction { + OperatorDeleteDeallocationFunction() { + exists(string name | + hasGlobalOrStdName(name) and + ( + // operator delete(pointer, ...) + name = "operator delete" or + // operator delete[](pointer, ...) + name = "operator delete[]" + ) + ) + } + + override int getFreedArg() { result = 0 } +} + /** * An deallocation expression that is a function call, such as call to `free`. */ diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index ce6a893af7f..2f9b4413e8c 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -85,6 +85,15 @@ allocationExprs | allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc | | allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc | deallocationFunctions +| allocators.cpp:11:6:11:20 | operator delete | getFreedArg = 0 | +| allocators.cpp:12:6:12:22 | operator delete[] | getFreedArg = 0 | +| allocators.cpp:13:6:13:20 | operator delete | getFreedArg = 0 | +| allocators.cpp:14:6:14:22 | operator delete[] | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 | deallocationExprs | allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 | | allocators.cpp:60:3:60:38 | delete | getFreedExpr = 0 | @@ -98,3 +107,4 @@ deallocationExprs | allocators.cpp:81:3:81:45 | delete[] | getFreedExpr = 0 | | allocators.cpp:82:3:82:49 | delete[] | getFreedExpr = 0 | | allocators.cpp:83:3:83:23 | delete[] | getFreedExpr = call to GetPointer | +| allocators.cpp:150:2:150:16 | call to operator delete | getFreedExpr = ptr | From a75e249112b1d6500b0d9d9c77c1b73699ac122e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 10:36:22 +0100 Subject: [PATCH 213/459] C++: Autoformat test. --- .../library-tests/allocators/allocators.ql | 71 ++++++++++--------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index 5993bf6d390..e45667fbf01 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -1,7 +1,9 @@ import default import semmle.code.cpp.models.implementations.Allocation -query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form, string placement) { +query predicate newExprs( + NewExpr expr, string type, string sig, int size, int alignment, string form, string placement +) { exists(Function allocator, Type allocatedType | expr.getAllocator() = allocator and sig = allocator.getFullSignature() and @@ -9,8 +11,10 @@ query predicate newExprs(NewExpr expr, string type, string sig, int size, int al type = allocatedType.toString() and size = allocatedType.getSize() and alignment = allocatedType.getAlignment() and - if expr.hasAlignedAllocation() then form = "aligned" else form = "" and - if exists(expr.getPlacementPointer()) then placement = expr.getPlacementPointer().toString() else placement = "" + (if expr.hasAlignedAllocation() then form = "aligned" else form = "") and + if exists(expr.getPlacementPointer()) + then placement = expr.getPlacementPointer().toString() + else placement = "" ) } @@ -29,7 +33,9 @@ query predicate newArrayExprs( alignment = elementType.getAlignment() and (if expr.hasAlignedAllocation() then form = "aligned" else form = "") and extents = concat(Expr e | e = expr.getExtent() | e.toString(), ", ") and - if exists(expr.getPlacementPointer()) then placement = expr.getPlacementPointer().toString() else placement = "" + if exists(expr.getPlacementPointer()) + then placement = expr.getPlacementPointer().toString() + else placement = "" ) } @@ -106,55 +112,52 @@ query predicate deleteArrayExprs( } string describeAllocationFunction(AllocationFunction f) { - result = "getSizeArg = " + f.getSizeArg().toString() - or - result = "getSizeMult = " + f.getSizeMult().toString() - or - result = "getReallocPtrArg = " + f.getReallocPtrArg().toString() - or - ( - f.requiresDealloc() and - result = "requiresDealloc" - ) - or - result = "getPlacementArgument = " + f.(OperatorNewAllocationFunction).getPlacementArgument().toString() + result = "getSizeArg = " + f.getSizeArg().toString() + or + result = "getSizeMult = " + f.getSizeMult().toString() + or + result = "getReallocPtrArg = " + f.getReallocPtrArg().toString() + or + f.requiresDealloc() and + result = "requiresDealloc" + or + result = + "getPlacementArgument = " + f.(OperatorNewAllocationFunction).getPlacementArgument().toString() } query predicate allocationFunctions(AllocationFunction f, string descr) { - descr = concat(describeAllocationFunction(f), ", ") + descr = concat(describeAllocationFunction(f), ", ") } string describeAllocationExpr(AllocationExpr e) { - result = "getSizeExpr = " + e.getSizeExpr().toString() - or - result = "getSizeMult = " + e.getSizeMult().toString() - or - result = "getSizeBytes = " + e.getSizeBytes().toString() - or - result = "getReallocPtr = " + e.getReallocPtr().toString() - or - ( - e.requiresDealloc() and - result = "requiresDealloc" - ) + result = "getSizeExpr = " + e.getSizeExpr().toString() + or + result = "getSizeMult = " + e.getSizeMult().toString() + or + result = "getSizeBytes = " + e.getSizeBytes().toString() + or + result = "getReallocPtr = " + e.getReallocPtr().toString() + or + e.requiresDealloc() and + result = "requiresDealloc" } query predicate allocationExprs(AllocationExpr e, string descr) { - descr = concat(describeAllocationExpr(e), ", ") + descr = concat(describeAllocationExpr(e), ", ") } string describeDeallocationFunction(DeallocationFunction f) { - result = "getFreedArg = " + f.getFreedArg().toString() + result = "getFreedArg = " + f.getFreedArg().toString() } query predicate deallocationFunctions(DeallocationFunction f, string descr) { - descr = concat(describeDeallocationFunction(f), ", ") + descr = concat(describeDeallocationFunction(f), ", ") } string describeDeallocationExpr(DeallocationExpr e) { - result = "getFreedExpr = " + e.getFreedExpr().toString() + result = "getFreedExpr = " + e.getFreedExpr().toString() } query predicate deallocationExprs(DeallocationExpr e, string descr) { - descr = concat(describeDeallocationExpr(e), ", ") + descr = concat(describeDeallocationExpr(e), ", ") } From bd89ee13d1c5a7cf3a0273973d4e83d85616b92f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 31 Mar 2020 13:56:32 +0200 Subject: [PATCH 214/459] C++: Add InitializeDynamicAllocation instruction to NewExpr and NewArrayExpr --- .../raw/internal/TranslatedCall.qll | 131 +++++++++++------- .../raw/internal/TranslatedElement.qll | 10 +- .../raw/internal/TranslatedExpr.qll | 5 + 3 files changed, 92 insertions(+), 54 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index fb7dc173812..a70cf1e45ba 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -7,6 +7,7 @@ private import InstructionTag private import TranslatedElement private import TranslatedExpr private import TranslatedFunction +private import semmle.code.cpp.models.implementations.Allocation /** * The IR translation of a call to a function. The call may be from an actual @@ -206,7 +207,44 @@ abstract class TranslatedCall extends TranslatedExpr { predicate hasPreciseSideEffect() { exists(getSideEffects()) } - TranslatedSideEffects getSideEffects() { result.getCall() = expr } + final TranslatedSideEffects getSideEffects() { result.getExpr() = expr } +} + +abstract class TranslatedSideEffects extends TranslatedElement { + abstract Expr getExpr(); + + final override Locatable getAST() { result = getExpr() } + + final override Function getFunction() { result = getExpr().getEnclosingFunction() } + + override TranslatedElement getChild(int i) { + result = + rank[i + 1](TranslatedSideEffect tse, int isWrite, int index | + ( + tse.getCall() = getExpr() and + tse.getArgumentIndex() = index and + if tse.isWrite() then isWrite = 1 else isWrite = 0 + ) + | + tse order by isWrite, index + ) + } + + final override Instruction getChildSuccessor(TranslatedElement te) { + exists(int i | + getChild(i) = te and + if exists(getChild(i + 1)) + then result = getChild(i + 1).getFirstInstruction() + else result = getParent().getChildSuccessor(this) + ) + } + + /** + * Gets the `TranslatedFunction` containing this expression. + */ + final TranslatedFunction getEnclosingFunction() { + result = getTranslatedFunction(getExpr().getEnclosingFunction()) + } } /** @@ -308,56 +346,27 @@ class TranslatedStructorCall extends TranslatedFunctionCall { override predicate hasQualifier() { any() } } -class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { - Call expr; +abstract class TranslatedAllocationSideEffects extends TranslatedSideEffects, + TTranslatedAllocationSideEffects { + AllocationExpr expr; - TranslatedSideEffects() { this = TTranslatedSideEffects(expr) } + TranslatedAllocationSideEffects() { this = TTranslatedAllocationSideEffects(expr) } - override string toString() { result = "(side effects for " + expr.toString() + ")" } + final override AllocationExpr getExpr() { result = expr } - override Locatable getAST() { result = expr } + override string toString() { result = "(allocation side effects for " + expr.toString() + ")" } - Call getCall() { result = expr } - - override TranslatedElement getChild(int i) { - result = - rank[i + 1](TranslatedSideEffect tse, int isWrite, int index | - ( - tse.getCall() = getCall() and - tse.getArgumentIndex() = index and - if tse.isWrite() then isWrite = 1 else isWrite = 0 - ) - | - tse order by isWrite, index - ) - } - - override Instruction getChildSuccessor(TranslatedElement te) { - exists(int i | - getChild(i) = te and - if exists(getChild(i + 1)) - then result = getChild(i + 1).getFirstInstruction() - else result = getParent().getChildSuccessor(this) - ) - } + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { - expr.getTarget() instanceof AllocationFunction and opcode instanceof Opcode::InitializeDynamicAllocation and tag = OnlyInstructionTag() and type = getUnknownType() } - override Instruction getFirstInstruction() { - if expr.getTarget() instanceof AllocationFunction - then result = getInstruction(OnlyInstructionTag()) - else result = getChild(0).getFirstInstruction() - } - override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind = gotoEdge() and - expr.getTarget() instanceof AllocationFunction and if exists(getChild(0)) then result = getChild(0).getFirstInstruction() else result = getParent().getChildSuccessor(this) @@ -368,26 +377,48 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { operandTag = addressOperand() and result = getPrimaryInstructionForSideEffect(OnlyInstructionTag()) } +} + +class TranslatedCallAllocationSideEffects extends TranslatedAllocationSideEffects { + override CallAllocationExpr expr; override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { tag = OnlyInstructionTag() and result = getTranslatedExpr(expr).getInstruction(CallTag()) } - - /** - * Gets the `TranslatedFunction` containing this expression. - */ - final TranslatedFunction getEnclosingFunction() { - result = getTranslatedFunction(expr.getEnclosingFunction()) - } - - /** - * Gets the `Function` containing this expression. - */ - override Function getFunction() { result = expr.getEnclosingFunction() } } -class TranslatedStructorCallSideEffects extends TranslatedSideEffects { +class TranslatedNewAllocationSideEffects extends TranslatedAllocationSideEffects { + override NewAllocationExpr expr; + + override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = getTranslatedAllocatorCall(expr).getInstruction(CallTag()) + } +} + +class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSideEffects { + Call expr; + + TranslatedCallSideEffects() { this = TTranslatedCallSideEffects(expr) } + + override string toString() { result = "(side effects for " + expr.toString() + ")" } + + override Call getExpr() { result = expr } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() } + + override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } + + override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = getTranslatedExpr(expr).getInstruction(CallTag()) + } +} + +class TranslatedStructorCallSideEffects extends TranslatedCallSideEffects { TranslatedStructorCallSideEffects() { getParent().(TranslatedStructorCall).hasQualifier() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType t) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 9b9c690990f..906bb375973 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -442,11 +442,13 @@ newtype TTranslatedElement = // The declaration/initialization part of a `ConditionDeclExpr` TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or // The side effects of a `Call` - TTranslatedSideEffects(Call expr) { + TTranslatedCallSideEffects(Call expr) { exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or - expr instanceof ConstructorCall or - expr.getTarget() instanceof AllocationFunction - } or // A precise side effect of an argument to a `Call` + expr instanceof ConstructorCall + } or + // The side effects of an allocation, i.e. `new`, `new[]` or `malloc` + TTranslatedAllocationSideEffects(AllocationExpr expr) or + // A precise side effect of an argument to a `Call` TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) { ( expr = call.getArgument(n).getFullyConverted() diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index c6c53a1842b..b8ede454ba2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -1649,6 +1649,11 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect final override int getNumberOfArguments() { result = expr.getAllocatorCall().getNumberOfArguments() + or + // Make sure there's a result even when there is no allocator, as otherwise + // TranslatedCall::getChild() will not return the side effects for this call. + not exists(expr.getAllocatorCall()) and + result = 0 } final override TranslatedExpr getArgument(int index) { From 94f5468504db88fccfc1b30bdf4993edfacd56d1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 31 Mar 2020 13:56:47 +0200 Subject: [PATCH 215/459] C++: Accept tests --- .../test/library-tests/ir/ir/raw_ir.expected | 66 ++++++++------ .../ir/ssa/aliased_ssa_ir.expected | 91 ++++++++++--------- .../ir/ssa/aliased_ssa_ir_unsound.expected | 91 ++++++++++--------- .../ir/ssa/unaliased_ssa_ir.expected | 69 +++++++------- .../ir/ssa/unaliased_ssa_ir_unsound.expected | 69 +++++++------- 5 files changed, 207 insertions(+), 179 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index e4bbac446ba..06aecc80298 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -4664,58 +4664,65 @@ ir.cpp: # 950| r950_2(unsigned long) = Constant[4] : # 950| r950_3(void *) = Call : func:r950_1, 0:r950_2 # 950| mu950_4(unknown) = ^CallSideEffect : ~mu949_4 -# 950| r950_5(int *) = Convert : r950_3 +# 950| mu950_5(unknown) = ^InitializeDynamicAllocation : &:r950_3 +# 950| r950_6(int *) = Convert : r950_3 # 951| r951_1(glval) = FunctionAddress[operator new] : # 951| r951_2(unsigned long) = Constant[4] : # 951| r951_3(float) = Constant[1.0] : # 951| r951_4(void *) = Call : func:r951_1, 0:r951_2, 1:r951_3 # 951| mu951_5(unknown) = ^CallSideEffect : ~mu949_4 -# 951| r951_6(int *) = Convert : r951_4 +# 951| mu951_6(unknown) = ^InitializeDynamicAllocation : &:r951_4 +# 951| r951_7(int *) = Convert : r951_4 # 952| r952_1(glval) = FunctionAddress[operator new] : # 952| r952_2(unsigned long) = Constant[4] : # 952| r952_3(void *) = Call : func:r952_1, 0:r952_2 # 952| mu952_4(unknown) = ^CallSideEffect : ~mu949_4 -# 952| r952_5(int *) = Convert : r952_3 -# 952| r952_6(int) = Constant[0] : -# 952| mu952_7(int) = Store : &:r952_5, r952_6 +# 952| mu952_5(unknown) = ^InitializeDynamicAllocation : &:r952_3 +# 952| r952_6(int *) = Convert : r952_3 +# 952| r952_7(int) = Constant[0] : +# 952| mu952_8(int) = Store : &:r952_6, r952_7 # 953| r953_1(glval) = FunctionAddress[operator new] : # 953| r953_2(unsigned long) = Constant[8] : # 953| r953_3(void *) = Call : func:r953_1, 0:r953_2 # 953| mu953_4(unknown) = ^CallSideEffect : ~mu949_4 -# 953| r953_5(String *) = Convert : r953_3 -# 953| r953_6(glval) = FunctionAddress[String] : -# 953| v953_7(void) = Call : func:r953_6, this:r953_5 -# 953| mu953_8(unknown) = ^CallSideEffect : ~mu949_4 -# 953| mu953_9(String) = ^IndirectMayWriteSideEffect[-1] : &:r953_5 +# 953| mu953_5(unknown) = ^InitializeDynamicAllocation : &:r953_3 +# 953| r953_6(String *) = Convert : r953_3 +# 953| r953_7(glval) = FunctionAddress[String] : +# 953| v953_8(void) = Call : func:r953_7, this:r953_6 +# 953| mu953_9(unknown) = ^CallSideEffect : ~mu949_4 +# 953| mu953_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r953_6 # 954| r954_1(glval) = FunctionAddress[operator new] : # 954| r954_2(unsigned long) = Constant[8] : # 954| r954_3(float) = Constant[1.0] : # 954| r954_4(void *) = Call : func:r954_1, 0:r954_2, 1:r954_3 # 954| mu954_5(unknown) = ^CallSideEffect : ~mu949_4 -# 954| r954_6(String *) = Convert : r954_4 -# 954| r954_7(glval) = FunctionAddress[String] : -# 954| r954_8(glval) = StringConstant["hello"] : -# 954| r954_9(char *) = Convert : r954_8 -# 954| v954_10(void) = Call : func:r954_7, this:r954_6, 0:r954_9 -# 954| mu954_11(unknown) = ^CallSideEffect : ~mu949_4 -# 954| mu954_12(String) = ^IndirectMayWriteSideEffect[-1] : &:r954_6 -# 954| v954_13(void) = ^BufferReadSideEffect[0] : &:r954_9, ~mu949_4 -# 954| mu954_14(unknown) = ^BufferMayWriteSideEffect[0] : &:r954_9 +# 954| mu954_6(unknown) = ^InitializeDynamicAllocation : &:r954_4 +# 954| r954_7(String *) = Convert : r954_4 +# 954| r954_8(glval) = FunctionAddress[String] : +# 954| r954_9(glval) = StringConstant["hello"] : +# 954| r954_10(char *) = Convert : r954_9 +# 954| v954_11(void) = Call : func:r954_8, this:r954_7, 0:r954_10 +# 954| mu954_12(unknown) = ^CallSideEffect : ~mu949_4 +# 954| mu954_13(String) = ^IndirectMayWriteSideEffect[-1] : &:r954_7 +# 954| v954_14(void) = ^BufferReadSideEffect[0] : &:r954_10, ~mu949_4 +# 954| mu954_15(unknown) = ^BufferMayWriteSideEffect[0] : &:r954_10 # 955| r955_1(glval) = FunctionAddress[operator new] : # 955| r955_2(unsigned long) = Constant[256] : # 955| r955_3(align_val_t) = Constant[128] : # 955| r955_4(void *) = Call : func:r955_1, 0:r955_2, 1:r955_3 # 955| mu955_5(unknown) = ^CallSideEffect : ~mu949_4 -# 955| r955_6(Overaligned *) = Convert : r955_4 +# 955| mu955_6(unknown) = ^InitializeDynamicAllocation : &:r955_4 +# 955| r955_7(Overaligned *) = Convert : r955_4 # 956| r956_1(glval) = FunctionAddress[operator new] : # 956| r956_2(unsigned long) = Constant[256] : # 956| r956_3(align_val_t) = Constant[128] : # 956| r956_4(float) = Constant[1.0] : # 956| r956_5(void *) = Call : func:r956_1, 0:r956_2, 1:r956_3, 2:r956_4 # 956| mu956_6(unknown) = ^CallSideEffect : ~mu949_4 -# 956| r956_7(Overaligned *) = Convert : r956_5 -# 956| r956_8(Overaligned) = Constant[0] : -# 956| mu956_9(Overaligned) = Store : &:r956_7, r956_8 +# 956| mu956_7(unknown) = ^InitializeDynamicAllocation : &:r956_5 +# 956| r956_8(Overaligned *) = Convert : r956_5 +# 956| r956_9(Overaligned) = Constant[0] : +# 956| mu956_10(Overaligned) = Store : &:r956_8, r956_9 # 957| v957_1(void) = NoOp : # 949| v949_5(void) = ReturnVoid : # 949| v949_6(void) = UnmodeledUse : mu* @@ -6447,12 +6454,13 @@ perf-regression.cpp: # 10| r10_3(unsigned long) = Constant[1073741824] : # 10| r10_4(void *) = Call : func:r10_2, 0:r10_3 # 10| mu10_5(unknown) = ^CallSideEffect : ~mu9_4 -# 10| r10_6(Big *) = Convert : r10_4 -# 10| r10_7(glval) = FunctionAddress[Big] : -# 10| v10_8(void) = Call : func:r10_7, this:r10_6 -# 10| mu10_9(unknown) = ^CallSideEffect : ~mu9_4 -# 10| mu10_10(Big) = ^IndirectMayWriteSideEffect[-1] : &:r10_6 -# 10| mu10_11(Big *) = Store : &:r10_1, r10_6 +# 10| mu10_6(unknown) = ^InitializeDynamicAllocation : &:r10_4 +# 10| r10_7(Big *) = Convert : r10_4 +# 10| r10_8(glval) = FunctionAddress[Big] : +# 10| v10_9(void) = Call : func:r10_8, this:r10_7 +# 10| mu10_10(unknown) = ^CallSideEffect : ~mu9_4 +# 10| mu10_11(Big) = ^IndirectMayWriteSideEffect[-1] : &:r10_7 +# 10| mu10_12(Big *) = Store : &:r10_1, r10_7 # 12| r12_1(glval) = VariableAddress[#return] : # 12| r12_2(int) = Constant[0] : # 12| mu12_3(int) = Store : &:r12_1, r12_2 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 76417701a35..c87d2060fb9 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -1410,69 +1410,74 @@ ssa.cpp: # 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 # 292| m292_5(unknown) = ^CallSideEffect : ~m291_4 # 292| m292_6(unknown) = Chi : total:m291_4, partial:m292_5 -# 292| r292_7(Point *) = Convert : r292_4 -# 292| m292_8(Point *) = Store : &:r292_1, r292_7 +# 292| m292_7(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_8(Point *) = Convert : r292_4 +# 292| m292_9(Point *) = Store : &:r292_1, r292_8 # 293| r293_1(glval) = VariableAddress[q] : # 293| r293_2(glval) = FunctionAddress[operator new] : # 293| r293_3(unsigned long) = Constant[8] : # 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 # 293| m293_5(unknown) = ^CallSideEffect : ~m292_6 # 293| m293_6(unknown) = Chi : total:m292_6, partial:m293_5 -# 293| r293_7(Point *) = Convert : r293_4 -# 293| m293_8(Point *) = Store : &:r293_1, r293_7 +# 293| m293_7(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_8(Point *) = Convert : r293_4 +# 293| m293_9(Point *) = Store : &:r293_1, r293_8 # 294| r294_1(glval) = VariableAddress[j] : # 294| r294_2(glval) = FunctionAddress[operator new] : # 294| r294_3(unsigned long) = Constant[4] : # 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 # 294| m294_5(unknown) = ^CallSideEffect : ~m293_6 # 294| m294_6(unknown) = Chi : total:m293_6, partial:m294_5 -# 294| r294_7(A *) = Convert : r294_4 -# 294| r294_8(glval) = FunctionAddress[A] : -# 294| r294_9(glval) = FunctionAddress[operator new] : -# 294| r294_10(unsigned long) = Constant[4] : -# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 -# 294| m294_12(unknown) = ^CallSideEffect : ~m294_6 -# 294| m294_13(unknown) = Chi : total:m294_6, partial:m294_12 -# 294| r294_14(A *) = Convert : r294_11 -# 294| r294_15(glval) = FunctionAddress[A] : -# 294| r294_16(glval) = VariableAddress[x] : -# 294| r294_17(int) = Load : &:r294_16, m291_7 -# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 -# 294| m294_19(unknown) = ^CallSideEffect : ~m294_13 -# 294| m294_20(unknown) = Chi : total:m294_13, partial:m294_19 -# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 -# 294| m294_22(unknown) = Chi : total:m294_20, partial:m294_21 -# 294| v294_23(void) = Call : func:r294_8, this:r294_7, 0:r294_14 -# 294| m294_24(unknown) = ^CallSideEffect : ~m294_22 -# 294| m294_25(unknown) = Chi : total:m294_22, partial:m294_24 -# 294| m294_26(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 -# 294| m294_27(unknown) = Chi : total:m294_25, partial:m294_26 -# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_14, ~m294_27 -# 294| m294_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 -# 294| m294_30(unknown) = Chi : total:m294_27, partial:m294_29 -# 294| r294_31(glval) = FieldAddress[i] : r294_7 -# 294| r294_32(int) = Load : &:r294_31, ~m294_30 -# 294| m294_33(int) = Store : &:r294_1, r294_32 +# 294| m294_7(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_8(A *) = Convert : r294_4 +# 294| r294_9(glval) = FunctionAddress[A] : +# 294| r294_10(glval) = FunctionAddress[operator new] : +# 294| r294_11(unsigned long) = Constant[4] : +# 294| r294_12(void *) = Call : func:r294_10, 0:r294_11 +# 294| m294_13(unknown) = ^CallSideEffect : ~m294_6 +# 294| m294_14(unknown) = Chi : total:m294_6, partial:m294_13 +# 294| m294_15(unknown) = ^InitializeDynamicAllocation : &:r294_12 +# 294| r294_16(A *) = Convert : r294_12 +# 294| r294_17(glval) = FunctionAddress[A] : +# 294| r294_18(glval) = VariableAddress[x] : +# 294| r294_19(int) = Load : &:r294_18, m291_7 +# 294| v294_20(void) = Call : func:r294_17, this:r294_16, 0:r294_19 +# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 +# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 +# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 +# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 +# 294| v294_25(void) = Call : func:r294_9, this:r294_8, 0:r294_16 +# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 +# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 +# 294| m294_28(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 +# 294| m294_29(unknown) = Chi : total:m294_7, partial:m294_28 +# 294| v294_30(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 +# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 +# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31 +# 294| r294_33(glval) = FieldAddress[i] : r294_8 +# 294| r294_34(int) = Load : &:r294_33, ~m294_29 +# 294| m294_35(int) = Store : &:r294_1, r294_34 # 295| r295_1(glval) = VariableAddress[a] : # 295| r295_2(glval) = FunctionAddress[operator new] : # 295| r295_3(unsigned long) = Constant[4] : # 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 -# 295| m295_5(unknown) = ^CallSideEffect : ~m294_30 -# 295| m295_6(unknown) = Chi : total:m294_30, partial:m295_5 -# 295| r295_7(A *) = Convert : r295_4 -# 295| r295_8(glval) = FunctionAddress[A] : -# 295| v295_9(void) = Call : func:r295_8, this:r295_7 -# 295| m295_10(unknown) = ^CallSideEffect : ~m295_6 -# 295| m295_11(unknown) = Chi : total:m295_6, partial:m295_10 -# 295| m295_12(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 -# 295| m295_13(unknown) = Chi : total:m295_11, partial:m295_12 -# 295| m295_14(A *) = Store : &:r295_1, r295_7 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 +# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 +# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_8(A *) = Convert : r295_4 +# 295| r295_9(glval) = FunctionAddress[A] : +# 295| v295_10(void) = Call : func:r295_9, this:r295_8 +# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 +# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 +# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 +# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13 +# 295| m295_15(A *) = Store : &:r295_1, r295_8 # 296| r296_1(glval) = VariableAddress[#return] : # 296| r296_2(glval) = VariableAddress[p] : -# 296| r296_3(Point *) = Load : &:r296_2, m292_8 +# 296| r296_3(Point *) = Load : &:r296_2, m292_9 # 296| m296_4(Point *) = Store : &:r296_1, r296_3 # 291| r291_8(glval) = VariableAddress[#return] : # 291| v291_9(void) = ReturnValue : &:r291_8, m296_4 # 291| v291_10(void) = UnmodeledUse : mu* -# 291| v291_11(void) = AliasedUse : ~m295_13 +# 291| v291_11(void) = AliasedUse : ~m295_12 # 291| v291_12(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index 3ee4d83a719..b354408d349 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1399,69 +1399,74 @@ ssa.cpp: # 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 # 292| m292_5(unknown) = ^CallSideEffect : ~m291_4 # 292| m292_6(unknown) = Chi : total:m291_4, partial:m292_5 -# 292| r292_7(Point *) = Convert : r292_4 -# 292| m292_8(Point *) = Store : &:r292_1, r292_7 +# 292| m292_7(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_8(Point *) = Convert : r292_4 +# 292| m292_9(Point *) = Store : &:r292_1, r292_8 # 293| r293_1(glval) = VariableAddress[q] : # 293| r293_2(glval) = FunctionAddress[operator new] : # 293| r293_3(unsigned long) = Constant[8] : # 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 # 293| m293_5(unknown) = ^CallSideEffect : ~m292_6 # 293| m293_6(unknown) = Chi : total:m292_6, partial:m293_5 -# 293| r293_7(Point *) = Convert : r293_4 -# 293| m293_8(Point *) = Store : &:r293_1, r293_7 +# 293| m293_7(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_8(Point *) = Convert : r293_4 +# 293| m293_9(Point *) = Store : &:r293_1, r293_8 # 294| r294_1(glval) = VariableAddress[j] : # 294| r294_2(glval) = FunctionAddress[operator new] : # 294| r294_3(unsigned long) = Constant[4] : # 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 # 294| m294_5(unknown) = ^CallSideEffect : ~m293_6 # 294| m294_6(unknown) = Chi : total:m293_6, partial:m294_5 -# 294| r294_7(A *) = Convert : r294_4 -# 294| r294_8(glval) = FunctionAddress[A] : -# 294| r294_9(glval) = FunctionAddress[operator new] : -# 294| r294_10(unsigned long) = Constant[4] : -# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 -# 294| m294_12(unknown) = ^CallSideEffect : ~m294_6 -# 294| m294_13(unknown) = Chi : total:m294_6, partial:m294_12 -# 294| r294_14(A *) = Convert : r294_11 -# 294| r294_15(glval) = FunctionAddress[A] : -# 294| r294_16(glval) = VariableAddress[x] : -# 294| r294_17(int) = Load : &:r294_16, m291_7 -# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 -# 294| m294_19(unknown) = ^CallSideEffect : ~m294_13 -# 294| m294_20(unknown) = Chi : total:m294_13, partial:m294_19 -# 294| m294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 -# 294| m294_22(unknown) = Chi : total:m294_20, partial:m294_21 -# 294| v294_23(void) = Call : func:r294_8, this:r294_7, 0:r294_14 -# 294| m294_24(unknown) = ^CallSideEffect : ~m294_22 -# 294| m294_25(unknown) = Chi : total:m294_22, partial:m294_24 -# 294| m294_26(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 -# 294| m294_27(unknown) = Chi : total:m294_25, partial:m294_26 -# 294| v294_28(void) = ^BufferReadSideEffect[0] : &:r294_14, ~m294_27 -# 294| m294_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 -# 294| m294_30(unknown) = Chi : total:m294_27, partial:m294_29 -# 294| r294_31(glval) = FieldAddress[i] : r294_7 -# 294| r294_32(int) = Load : &:r294_31, ~m294_30 -# 294| m294_33(int) = Store : &:r294_1, r294_32 +# 294| m294_7(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_8(A *) = Convert : r294_4 +# 294| r294_9(glval) = FunctionAddress[A] : +# 294| r294_10(glval) = FunctionAddress[operator new] : +# 294| r294_11(unsigned long) = Constant[4] : +# 294| r294_12(void *) = Call : func:r294_10, 0:r294_11 +# 294| m294_13(unknown) = ^CallSideEffect : ~m294_6 +# 294| m294_14(unknown) = Chi : total:m294_6, partial:m294_13 +# 294| m294_15(unknown) = ^InitializeDynamicAllocation : &:r294_12 +# 294| r294_16(A *) = Convert : r294_12 +# 294| r294_17(glval) = FunctionAddress[A] : +# 294| r294_18(glval) = VariableAddress[x] : +# 294| r294_19(int) = Load : &:r294_18, m291_7 +# 294| v294_20(void) = Call : func:r294_17, this:r294_16, 0:r294_19 +# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 +# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 +# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 +# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 +# 294| v294_25(void) = Call : func:r294_9, this:r294_8, 0:r294_16 +# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 +# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 +# 294| m294_28(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 +# 294| m294_29(unknown) = Chi : total:m294_7, partial:m294_28 +# 294| v294_30(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 +# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 +# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31 +# 294| r294_33(glval) = FieldAddress[i] : r294_8 +# 294| r294_34(int) = Load : &:r294_33, ~m294_29 +# 294| m294_35(int) = Store : &:r294_1, r294_34 # 295| r295_1(glval) = VariableAddress[a] : # 295| r295_2(glval) = FunctionAddress[operator new] : # 295| r295_3(unsigned long) = Constant[4] : # 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 -# 295| m295_5(unknown) = ^CallSideEffect : ~m294_30 -# 295| m295_6(unknown) = Chi : total:m294_30, partial:m295_5 -# 295| r295_7(A *) = Convert : r295_4 -# 295| r295_8(glval) = FunctionAddress[A] : -# 295| v295_9(void) = Call : func:r295_8, this:r295_7 -# 295| m295_10(unknown) = ^CallSideEffect : ~m295_6 -# 295| m295_11(unknown) = Chi : total:m295_6, partial:m295_10 -# 295| m295_12(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 -# 295| m295_13(unknown) = Chi : total:m295_11, partial:m295_12 -# 295| m295_14(A *) = Store : &:r295_1, r295_7 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 +# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 +# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_8(A *) = Convert : r295_4 +# 295| r295_9(glval) = FunctionAddress[A] : +# 295| v295_10(void) = Call : func:r295_9, this:r295_8 +# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 +# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 +# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 +# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13 +# 295| m295_15(A *) = Store : &:r295_1, r295_8 # 296| r296_1(glval) = VariableAddress[#return] : # 296| r296_2(glval) = VariableAddress[p] : -# 296| r296_3(Point *) = Load : &:r296_2, m292_8 +# 296| r296_3(Point *) = Load : &:r296_2, m292_9 # 296| m296_4(Point *) = Store : &:r296_1, r296_3 # 291| r291_8(glval) = VariableAddress[#return] : # 291| v291_9(void) = ReturnValue : &:r291_8, m296_4 # 291| v291_10(void) = UnmodeledUse : mu* -# 291| v291_11(void) = AliasedUse : ~m295_13 +# 291| v291_11(void) = AliasedUse : ~m295_12 # 291| v291_12(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 3627c6493f3..cbaf532bffa 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -1298,55 +1298,60 @@ ssa.cpp: # 292| r292_3(unsigned long) = Constant[8] : # 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 # 292| mu292_5(unknown) = ^CallSideEffect : ~mu291_4 -# 292| r292_6(Point *) = Convert : r292_4 -# 292| m292_7(Point *) = Store : &:r292_1, r292_6 +# 292| mu292_6(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_7(Point *) = Convert : r292_4 +# 292| m292_8(Point *) = Store : &:r292_1, r292_7 # 293| r293_1(glval) = VariableAddress[q] : # 293| r293_2(glval) = FunctionAddress[operator new] : # 293| r293_3(unsigned long) = Constant[8] : # 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 # 293| mu293_5(unknown) = ^CallSideEffect : ~mu291_4 -# 293| r293_6(Point *) = Convert : r293_4 -# 293| m293_7(Point *) = Store : &:r293_1, r293_6 +# 293| mu293_6(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_7(Point *) = Convert : r293_4 +# 293| m293_8(Point *) = Store : &:r293_1, r293_7 # 294| r294_1(glval) = VariableAddress[j] : # 294| r294_2(glval) = FunctionAddress[operator new] : # 294| r294_3(unsigned long) = Constant[4] : # 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 # 294| mu294_5(unknown) = ^CallSideEffect : ~mu291_4 -# 294| r294_6(A *) = Convert : r294_4 -# 294| r294_7(glval) = FunctionAddress[A] : -# 294| r294_8(glval) = FunctionAddress[operator new] : -# 294| r294_9(unsigned long) = Constant[4] : -# 294| r294_10(void *) = Call : func:r294_8, 0:r294_9 -# 294| mu294_11(unknown) = ^CallSideEffect : ~mu291_4 -# 294| r294_12(A *) = Convert : r294_10 -# 294| r294_13(glval) = FunctionAddress[A] : -# 294| r294_14(glval) = VariableAddress[x] : -# 294| r294_15(int) = Load : &:r294_14, m291_6 -# 294| v294_16(void) = Call : func:r294_13, this:r294_12, 0:r294_15 -# 294| mu294_17(unknown) = ^CallSideEffect : ~mu291_4 -# 294| mu294_18(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_12 -# 294| v294_19(void) = Call : func:r294_7, this:r294_6, 0:r294_12 -# 294| mu294_20(unknown) = ^CallSideEffect : ~mu291_4 -# 294| mu294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_6 -# 294| v294_22(void) = ^BufferReadSideEffect[0] : &:r294_12, ~mu291_4 -# 294| mu294_23(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_12 -# 294| r294_24(glval) = FieldAddress[i] : r294_6 -# 294| r294_25(int) = Load : &:r294_24, ~mu291_4 -# 294| m294_26(int) = Store : &:r294_1, r294_25 +# 294| mu294_6(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_7(A *) = Convert : r294_4 +# 294| r294_8(glval) = FunctionAddress[A] : +# 294| r294_9(glval) = FunctionAddress[operator new] : +# 294| r294_10(unsigned long) = Constant[4] : +# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 +# 294| mu294_12(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_13(unknown) = ^InitializeDynamicAllocation : &:r294_11 +# 294| r294_14(A *) = Convert : r294_11 +# 294| r294_15(glval) = FunctionAddress[A] : +# 294| r294_16(glval) = VariableAddress[x] : +# 294| r294_17(int) = Load : &:r294_16, m291_6 +# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 +# 294| mu294_19(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_20(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 +# 294| v294_21(void) = Call : func:r294_8, this:r294_7, 0:r294_14 +# 294| mu294_22(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 +# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_14, ~mu291_4 +# 294| mu294_25(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 +# 294| r294_26(glval) = FieldAddress[i] : r294_7 +# 294| r294_27(int) = Load : &:r294_26, ~mu291_4 +# 294| m294_28(int) = Store : &:r294_1, r294_27 # 295| r295_1(glval) = VariableAddress[a] : # 295| r295_2(glval) = FunctionAddress[operator new] : # 295| r295_3(unsigned long) = Constant[4] : # 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 # 295| mu295_5(unknown) = ^CallSideEffect : ~mu291_4 -# 295| r295_6(A *) = Convert : r295_4 -# 295| r295_7(glval) = FunctionAddress[A] : -# 295| v295_8(void) = Call : func:r295_7, this:r295_6 -# 295| mu295_9(unknown) = ^CallSideEffect : ~mu291_4 -# 295| mu295_10(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_6 -# 295| m295_11(A *) = Store : &:r295_1, r295_6 +# 295| mu295_6(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_7(A *) = Convert : r295_4 +# 295| r295_8(glval) = FunctionAddress[A] : +# 295| v295_9(void) = Call : func:r295_8, this:r295_7 +# 295| mu295_10(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 +# 295| m295_12(A *) = Store : &:r295_1, r295_7 # 296| r296_1(glval) = VariableAddress[#return] : # 296| r296_2(glval) = VariableAddress[p] : -# 296| r296_3(Point *) = Load : &:r296_2, m292_7 +# 296| r296_3(Point *) = Load : &:r296_2, m292_8 # 296| m296_4(Point *) = Store : &:r296_1, r296_3 # 291| r291_7(glval) = VariableAddress[#return] : # 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index 3627c6493f3..cbaf532bffa 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -1298,55 +1298,60 @@ ssa.cpp: # 292| r292_3(unsigned long) = Constant[8] : # 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 # 292| mu292_5(unknown) = ^CallSideEffect : ~mu291_4 -# 292| r292_6(Point *) = Convert : r292_4 -# 292| m292_7(Point *) = Store : &:r292_1, r292_6 +# 292| mu292_6(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_7(Point *) = Convert : r292_4 +# 292| m292_8(Point *) = Store : &:r292_1, r292_7 # 293| r293_1(glval) = VariableAddress[q] : # 293| r293_2(glval) = FunctionAddress[operator new] : # 293| r293_3(unsigned long) = Constant[8] : # 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 # 293| mu293_5(unknown) = ^CallSideEffect : ~mu291_4 -# 293| r293_6(Point *) = Convert : r293_4 -# 293| m293_7(Point *) = Store : &:r293_1, r293_6 +# 293| mu293_6(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_7(Point *) = Convert : r293_4 +# 293| m293_8(Point *) = Store : &:r293_1, r293_7 # 294| r294_1(glval) = VariableAddress[j] : # 294| r294_2(glval) = FunctionAddress[operator new] : # 294| r294_3(unsigned long) = Constant[4] : # 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 # 294| mu294_5(unknown) = ^CallSideEffect : ~mu291_4 -# 294| r294_6(A *) = Convert : r294_4 -# 294| r294_7(glval) = FunctionAddress[A] : -# 294| r294_8(glval) = FunctionAddress[operator new] : -# 294| r294_9(unsigned long) = Constant[4] : -# 294| r294_10(void *) = Call : func:r294_8, 0:r294_9 -# 294| mu294_11(unknown) = ^CallSideEffect : ~mu291_4 -# 294| r294_12(A *) = Convert : r294_10 -# 294| r294_13(glval) = FunctionAddress[A] : -# 294| r294_14(glval) = VariableAddress[x] : -# 294| r294_15(int) = Load : &:r294_14, m291_6 -# 294| v294_16(void) = Call : func:r294_13, this:r294_12, 0:r294_15 -# 294| mu294_17(unknown) = ^CallSideEffect : ~mu291_4 -# 294| mu294_18(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_12 -# 294| v294_19(void) = Call : func:r294_7, this:r294_6, 0:r294_12 -# 294| mu294_20(unknown) = ^CallSideEffect : ~mu291_4 -# 294| mu294_21(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_6 -# 294| v294_22(void) = ^BufferReadSideEffect[0] : &:r294_12, ~mu291_4 -# 294| mu294_23(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_12 -# 294| r294_24(glval) = FieldAddress[i] : r294_6 -# 294| r294_25(int) = Load : &:r294_24, ~mu291_4 -# 294| m294_26(int) = Store : &:r294_1, r294_25 +# 294| mu294_6(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_7(A *) = Convert : r294_4 +# 294| r294_8(glval) = FunctionAddress[A] : +# 294| r294_9(glval) = FunctionAddress[operator new] : +# 294| r294_10(unsigned long) = Constant[4] : +# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 +# 294| mu294_12(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_13(unknown) = ^InitializeDynamicAllocation : &:r294_11 +# 294| r294_14(A *) = Convert : r294_11 +# 294| r294_15(glval) = FunctionAddress[A] : +# 294| r294_16(glval) = VariableAddress[x] : +# 294| r294_17(int) = Load : &:r294_16, m291_6 +# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 +# 294| mu294_19(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_20(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 +# 294| v294_21(void) = Call : func:r294_8, this:r294_7, 0:r294_14 +# 294| mu294_22(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 +# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_14, ~mu291_4 +# 294| mu294_25(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 +# 294| r294_26(glval) = FieldAddress[i] : r294_7 +# 294| r294_27(int) = Load : &:r294_26, ~mu291_4 +# 294| m294_28(int) = Store : &:r294_1, r294_27 # 295| r295_1(glval) = VariableAddress[a] : # 295| r295_2(glval) = FunctionAddress[operator new] : # 295| r295_3(unsigned long) = Constant[4] : # 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 # 295| mu295_5(unknown) = ^CallSideEffect : ~mu291_4 -# 295| r295_6(A *) = Convert : r295_4 -# 295| r295_7(glval) = FunctionAddress[A] : -# 295| v295_8(void) = Call : func:r295_7, this:r295_6 -# 295| mu295_9(unknown) = ^CallSideEffect : ~mu291_4 -# 295| mu295_10(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_6 -# 295| m295_11(A *) = Store : &:r295_1, r295_6 +# 295| mu295_6(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_7(A *) = Convert : r295_4 +# 295| r295_8(glval) = FunctionAddress[A] : +# 295| v295_9(void) = Call : func:r295_8, this:r295_7 +# 295| mu295_10(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 +# 295| m295_12(A *) = Store : &:r295_1, r295_7 # 296| r296_1(glval) = VariableAddress[#return] : # 296| r296_2(glval) = VariableAddress[p] : -# 296| r296_3(Point *) = Load : &:r296_2, m292_7 +# 296| r296_3(Point *) = Load : &:r296_2, m292_8 # 296| m296_4(Point *) = Store : &:r296_1, r296_3 # 291| r291_7(glval) = VariableAddress[#return] : # 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 From 4ca5e3755f548b1ebcd6a7a5b5a18c6fa5728c90 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 30 Mar 2020 15:14:07 +0200 Subject: [PATCH 216/459] C#: Add false-positive test for NullMaybe.ql --- csharp/ql/test/query-tests/Nullness/E.cs | 9 +++++ .../Nullness/EqualityCheck.expected | 14 +++++++ .../Nullness/Implications.expected | 20 ++++++++++ .../query-tests/Nullness/NullCheck.expected | 12 ++++++ .../query-tests/Nullness/NullMaybe.expected | 37 +++++++++++++++++++ 5 files changed, 92 insertions(+) diff --git a/csharp/ql/test/query-tests/Nullness/E.cs b/csharp/ql/test/query-tests/Nullness/E.cs index 0c020e9b150..67b5267ffbe 100644 --- a/csharp/ql/test/query-tests/Nullness/E.cs +++ b/csharp/ql/test/query-tests/Nullness/E.cs @@ -376,6 +376,15 @@ public class E } return -1; } + + static bool Ex37(E e1, E e2) + { + if ((e1 == null && e2 != null) || (e1 != null && e2 == null)) + return false; + if (e1 == null && e2 == null) + return true; + return e1.Long == e2.Long; // GOOD (false positive) + } } public static class Extensions diff --git a/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected b/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected index 2aa5b3f4f5e..5f739e93c2b 100644 --- a/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected +++ b/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected @@ -220,6 +220,20 @@ | E.cs:355:13:355:21 | dynamic call to operator != | false | E.cs:355:18:355:21 | null | E.cs:355:13:355:13 | access to local variable x | | E.cs:362:13:362:29 | ... != ... | false | E.cs:362:13:362:13 | access to local variable x | E.cs:362:18:362:29 | (...) ... | | E.cs:362:13:362:29 | ... != ... | false | E.cs:362:18:362:29 | (...) ... | E.cs:362:13:362:13 | access to local variable x | +| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:14:382:15 | access to parameter e1 | E.cs:382:20:382:23 | null | +| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:20:382:23 | null | E.cs:382:14:382:15 | access to parameter e1 | +| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:34:382:37 | null | +| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:34:382:37 | null | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:44:382:45 | access to parameter e1 | E.cs:382:50:382:53 | null | +| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:50:382:53 | null | E.cs:382:44:382:45 | access to parameter e1 | +| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:58:382:59 | access to parameter e2 | E.cs:382:64:382:67 | null | +| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:64:382:67 | null | E.cs:382:58:382:59 | access to parameter e2 | +| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:13:384:14 | access to parameter e1 | E.cs:384:19:384:22 | null | +| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:19:384:22 | null | E.cs:384:13:384:14 | access to parameter e1 | +| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:27:384:28 | access to parameter e2 | E.cs:384:33:384:36 | null | +| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:33:384:36 | null | E.cs:384:27:384:28 | access to parameter e2 | +| E.cs:386:16:386:33 | ... == ... | true | E.cs:386:16:386:22 | access to property Long | E.cs:386:27:386:33 | access to property Long | +| E.cs:386:16:386:33 | ... == ... | true | E.cs:386:27:386:33 | access to property Long | E.cs:386:16:386:22 | access to property Long | | Forwarding.cs:59:13:59:21 | ... == ... | true | Forwarding.cs:59:13:59:13 | access to parameter o | Forwarding.cs:59:18:59:21 | null | | Forwarding.cs:59:13:59:21 | ... == ... | true | Forwarding.cs:59:18:59:21 | null | Forwarding.cs:59:13:59:13 | access to parameter o | | Forwarding.cs:78:16:78:39 | call to method ReferenceEquals | true | Forwarding.cs:78:32:78:32 | access to parameter o | Forwarding.cs:78:35:78:38 | null | diff --git a/csharp/ql/test/query-tests/Nullness/Implications.expected b/csharp/ql/test/query-tests/Nullness/Implications.expected index cbb2de7cafc..d7a06795fc2 100644 --- a/csharp/ql/test/query-tests/Nullness/Implications.expected +++ b/csharp/ql/test/query-tests/Nullness/Implications.expected @@ -1236,6 +1236,26 @@ | E.cs:375:20:375:20 | access to local variable s | non-empty | E.cs:374:21:374:31 | ... as ... | non-empty | | E.cs:375:20:375:20 | access to local variable s | non-null | E.cs:374:21:374:31 | ... as ... | non-null | | E.cs:375:20:375:20 | access to local variable s | null | E.cs:374:21:374:31 | ... as ... | null | +| E.cs:382:13:382:68 | ... \|\| ... | false | E.cs:382:14:382:37 | ... && ... | false | +| E.cs:382:13:382:68 | ... \|\| ... | false | E.cs:382:44:382:67 | ... && ... | false | +| E.cs:382:14:382:23 | ... == ... | false | E.cs:382:14:382:15 | access to parameter e1 | non-null | +| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:14:382:15 | access to parameter e1 | null | +| E.cs:382:14:382:37 | ... && ... | true | E.cs:382:14:382:23 | ... == ... | true | +| E.cs:382:14:382:37 | ... && ... | true | E.cs:382:28:382:37 | ... != ... | true | +| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:28:382:29 | access to parameter e2 | null | +| E.cs:382:28:382:37 | ... != ... | true | E.cs:382:28:382:29 | access to parameter e2 | non-null | +| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:44:382:45 | access to parameter e1 | null | +| E.cs:382:44:382:53 | ... != ... | true | E.cs:382:44:382:45 | access to parameter e1 | non-null | +| E.cs:382:44:382:67 | ... && ... | true | E.cs:382:44:382:53 | ... != ... | true | +| E.cs:382:44:382:67 | ... && ... | true | E.cs:382:58:382:67 | ... == ... | true | +| E.cs:382:58:382:67 | ... == ... | false | E.cs:382:58:382:59 | access to parameter e2 | non-null | +| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:58:382:59 | access to parameter e2 | null | +| E.cs:384:13:384:22 | ... == ... | false | E.cs:384:13:384:14 | access to parameter e1 | non-null | +| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:13:384:14 | access to parameter e1 | null | +| E.cs:384:13:384:36 | ... && ... | true | E.cs:384:13:384:22 | ... == ... | true | +| E.cs:384:13:384:36 | ... && ... | true | E.cs:384:27:384:36 | ... == ... | true | +| E.cs:384:27:384:36 | ... == ... | false | E.cs:384:27:384:28 | access to parameter e2 | non-null | +| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:27:384:28 | access to parameter e2 | null | | Forwarding.cs:9:13:9:30 | !... | false | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | true | | Forwarding.cs:9:13:9:30 | !... | true | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | false | | Forwarding.cs:9:14:9:14 | access to local variable s | empty | Forwarding.cs:7:20:7:23 | null | empty | diff --git a/csharp/ql/test/query-tests/Nullness/NullCheck.expected b/csharp/ql/test/query-tests/Nullness/NullCheck.expected index d9fcd0121f9..1c2b22ca6b5 100644 --- a/csharp/ql/test/query-tests/Nullness/NullCheck.expected +++ b/csharp/ql/test/query-tests/Nullness/NullCheck.expected @@ -264,6 +264,18 @@ | E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | false | true | | E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | true | false | | E.cs:372:13:372:23 | ... is ... | E.cs:372:13:372:13 | access to parameter o | true | false | +| E.cs:382:14:382:23 | ... == ... | E.cs:382:14:382:15 | access to parameter e1 | false | false | +| E.cs:382:14:382:23 | ... == ... | E.cs:382:14:382:15 | access to parameter e1 | true | true | +| E.cs:382:28:382:37 | ... != ... | E.cs:382:28:382:29 | access to parameter e2 | false | true | +| E.cs:382:28:382:37 | ... != ... | E.cs:382:28:382:29 | access to parameter e2 | true | false | +| E.cs:382:44:382:53 | ... != ... | E.cs:382:44:382:45 | access to parameter e1 | false | true | +| E.cs:382:44:382:53 | ... != ... | E.cs:382:44:382:45 | access to parameter e1 | true | false | +| E.cs:382:58:382:67 | ... == ... | E.cs:382:58:382:59 | access to parameter e2 | false | false | +| E.cs:382:58:382:67 | ... == ... | E.cs:382:58:382:59 | access to parameter e2 | true | true | +| E.cs:384:13:384:22 | ... == ... | E.cs:384:13:384:14 | access to parameter e1 | false | false | +| E.cs:384:13:384:22 | ... == ... | E.cs:384:13:384:14 | access to parameter e1 | true | true | +| E.cs:384:27:384:36 | ... == ... | E.cs:384:27:384:28 | access to parameter e2 | false | false | +| E.cs:384:27:384:36 | ... == ... | E.cs:384:27:384:28 | access to parameter e2 | true | true | | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | Forwarding.cs:9:14:9:14 | access to local variable s | false | false | | Forwarding.cs:14:13:14:32 | call to method IsNotNullOrEmpty | Forwarding.cs:14:13:14:13 | access to local variable s | true | false | | Forwarding.cs:19:14:19:23 | call to method IsNull | Forwarding.cs:19:14:19:14 | access to local variable s | false | false | diff --git a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected index acc3a29817c..4d4f9344986 100644 --- a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected @@ -355,6 +355,21 @@ nodes | E.cs:366:41:366:41 | access to parameter s | | E.cs:374:17:374:31 | SSA def(s) | | E.cs:375:20:375:20 | access to local variable s | +| E.cs:380:24:380:25 | SSA param(e1) | +| E.cs:380:24:380:25 | SSA param(e1) | +| E.cs:380:24:380:25 | SSA param(e1) | +| E.cs:380:30:380:31 | SSA param(e2) | +| E.cs:380:30:380:31 | SSA param(e2) | +| E.cs:380:30:380:31 | SSA param(e2) | +| E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:382:44:382:67 | ... && ... | +| E.cs:382:44:382:67 | ... && ... | +| E.cs:384:9:385:24 | if (...) ... | +| E.cs:384:9:385:24 | if (...) ... | +| E.cs:384:27:384:28 | access to parameter e2 | +| E.cs:386:16:386:17 | access to parameter e1 | +| E.cs:386:27:386:28 | access to parameter e2 | | Forwarding.cs:7:16:7:23 | SSA def(s) | | Forwarding.cs:14:9:17:9 | if (...) ... | | Forwarding.cs:19:9:22:9 | if (...) ... | @@ -688,6 +703,22 @@ edges | E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x | | E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s | | E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s | +| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... | +| E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:44:382:67 | ... && ... | +| E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:44:382:67 | ... && ... | +| E.cs:382:44:382:67 | ... && ... | E.cs:384:9:385:24 | if (...) ... | +| E.cs:382:44:382:67 | ... && ... | E.cs:384:9:385:24 | if (...) ... | +| E.cs:384:9:385:24 | if (...) ... | E.cs:384:27:384:28 | access to parameter e2 | +| E.cs:384:9:385:24 | if (...) ... | E.cs:386:27:386:28 | access to parameter e2 | +| E.cs:384:27:384:28 | access to parameter e2 | E.cs:386:16:386:17 | access to parameter e1 | | Forwarding.cs:7:16:7:23 | SSA def(s) | Forwarding.cs:14:9:17:9 | if (...) ... | | Forwarding.cs:14:9:17:9 | if (...) ... | Forwarding.cs:19:9:22:9 | if (...) ... | | Forwarding.cs:19:9:22:9 | if (...) ... | Forwarding.cs:24:9:27:9 | if (...) ... | @@ -790,6 +821,12 @@ edges | E.cs:349:9:349:9 | access to local variable x | E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x | Variable $@ may be null here because of $@ assignment. | E.cs:348:17:348:17 | x | x | E.cs:348:17:348:36 | dynamic x = ... | this | | E.cs:366:41:366:41 | access to parameter s | E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s | Variable $@ may be null here because the parameter has a null default value. | E.cs:366:28:366:28 | s | s | E.cs:366:32:366:35 | null | this | | E.cs:375:20:375:20 | access to local variable s | E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s | Variable $@ may be null here because of $@ assignment. | E.cs:374:17:374:17 | s | s | E.cs:374:17:374:31 | String s = ... | this | +| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:382:14:382:23 | ... == ... | this | +| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:382:44:382:53 | ... != ... | this | +| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:384:13:384:22 | ... == ... | this | +| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:28:382:37 | ... != ... | this | +| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:58:382:67 | ... == ... | this | +| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:384:27:384:36 | ... == ... | this | | GuardedString.cs:35:31:35:31 | access to local variable s | GuardedString.cs:7:16:7:32 | SSA def(s) | GuardedString.cs:35:31:35:31 | access to local variable s | Variable $@ may be null here because of $@ assignment. | GuardedString.cs:7:16:7:16 | s | s | GuardedString.cs:7:16:7:32 | String s = ... | this | | NullMaybeBad.cs:7:27:7:27 | access to parameter o | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | Variable $@ may be null here because of $@ null argument. | NullMaybeBad.cs:5:25:5:25 | o | o | NullMaybeBad.cs:13:17:13:20 | null | this | | StringConcatenation.cs:16:17:16:17 | access to local variable s | StringConcatenation.cs:14:16:14:23 | SSA def(s) | StringConcatenation.cs:16:17:16:17 | access to local variable s | Variable $@ may be null here because of $@ assignment. | StringConcatenation.cs:14:16:14:16 | s | s | StringConcatenation.cs:14:16:14:23 | String s = ... | this | From aa13257c1bb371db9d2366e2afba2ef65919920a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 14:37:54 +0100 Subject: [PATCH 217/459] C++: Correct QLDoc. --- .../src/semmle/code/cpp/models/implementations/Allocation.qll | 4 ++-- .../semmle/code/cpp/models/implementations/Deallocation.qll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index 9461213f56c..1454f64f509 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -216,8 +216,8 @@ class SizelessAllocationFunction extends AllocationFunction { } /** - * An `operator new` or `operator new[]` function that may be associated with a `new` or - * `new[]` expression. Note that `new` and `new[]` are not function calls, but these + * An `operator new` or `operator new[]` function that may be associated with `new` or + * `new[]` expressions. Note that `new` and `new[]` are not function calls, but these * functions may also be called directly. */ class OperatorNewAllocationFunction extends AllocationFunction { diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index c3b4cdd6584..35aa5c2227a 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -81,7 +81,7 @@ class StandardDeallocationFunction extends DeallocationFunction { /** * An `operator delete` or `operator delete[]` function that may be associated - * with a `delete` or `delete[]` expression. Note that `delete` and `delete[]` + * with `delete` or `delete[]` expressions. Note that `delete` and `delete[]` * are not function calls, but these functions may also be called directly. */ class OperatorDeleteDeallocationFunction extends DeallocationFunction { From b6f93746bf964ed25638bf16589da3269e4d1566 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 31 Mar 2020 16:00:56 +0200 Subject: [PATCH 218/459] C++: Accept test output --- cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 02a088752dd..082bbafa0f1 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -57,6 +57,7 @@ instructionWithoutSuccessor | condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | | condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | | condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | +| cpp17.cpp:15:5:15:45 | InitializeDynamicAllocation: new | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | file://:0:0:0:0 | CompareNE: (bool)... | | file://:0:0:0:0 | CompareNE: (bool)... | From 9a5e80667e3941647a80eeacb0950b35b6d2df56 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Tue, 31 Mar 2020 15:21:51 +0100 Subject: [PATCH 219/459] C#: Address review comments. --- .../Semmle.Autobuild/AutobuildOptions.cs | 9 +--- .../Semmle.Autobuild/Autobuilder.cs | 54 +++++++------------ .../Semmle.Util/CanonicalPathCache.cs | 4 +- 3 files changed, 23 insertions(+), 44 deletions(-) diff --git a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs index e89ca1a4663..d7b973dd350 100644 --- a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs @@ -107,13 +107,8 @@ namespace Semmle.Autobuild static readonly Regex linuxEnvRegEx = new Regex(@"\$([a-zA-Z_][a-zA-Z_0-9]*)", RegexOptions.Compiled); - public static string? AsStringWithExpandedEnvVarsMaybeNull(this string? value, IBuildActions actions) - { - if (string.IsNullOrEmpty(value)) - return value; - - return value.AsStringWithExpandedEnvVars(actions); - } + public static string? AsStringWithExpandedEnvVarsMaybeNull(this string? value, IBuildActions actions) => + value?.AsStringWithExpandedEnvVars(actions); public static string AsStringWithExpandedEnvVars(this string value, IBuildActions actions) { diff --git a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs index 3eda9a0473e..f6dbdae788c 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs @@ -185,34 +185,28 @@ namespace Semmle.Autobuild }); CodeQLExtractorCSharpRoot = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_ROOT"); - SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST"); - - CodeQLJavaHome = Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME"); - - SemmleJavaHome = Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME"); - - if(CodeQLJavaHome is null && SemmleJavaHome is null) - throw new InvalidEnvironmentException("The environment variables CODEQL_JAVA_HOME and SEMMLE_JAVA_HOME have not been set."); - SemmlePlatformTools = Actions.GetEnvironmentVariable("SEMMLE_PLATFORM_TOOLS"); - if (CodeQLExtractorCSharpRoot is null && SemmleDist is null) - throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_ROOT and SEMMLE_DIST have not been set."); + JavaHome = + Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME") ?? + Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME") ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_JAVA_HOME or SEMMLE_JAVA_HOME has not been set."); - var trapDir = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? Actions.GetEnvironmentVariable("TRAP_FOLDER"); + Distribution = + CodeQLExtractorCSharpRoot ?? + SemmleDist ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_EXTRACTOR_CSHARP_ROOT or SEMMLE_DIST has not been set."); - if (trapDir is null) - throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_TRAP_DIR and TRAP_FOLDER have not been set."); + TrapDir = + Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? + Actions.GetEnvironmentVariable("TRAP_FOLDER") ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_EXTRACTOR_CSHARP_TRAP_DIR or TRAP_FOLDER has not been set."); - TrapDir = trapDir; - - var sourceArchiveDir = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? Actions.GetEnvironmentVariable("SOURCE_ARCHIVE"); - - if(sourceArchiveDir is null) - throw new InvalidEnvironmentException("The environment variables CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR and SOURCE_ARCHIVE have not been set."); - - SourceArchiveDir = sourceArchiveDir; + SourceArchiveDir = + Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? + Actions.GetEnvironmentVariable("SOURCE_ARCHIVE") ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR or SOURCE_ARCHIVE has not been set."); } private string TrapDir { get; } @@ -407,29 +401,19 @@ namespace Semmle.Autobuild ///
    private string? CodeQLExtractorCSharpRoot { get; } - /// - /// Value of CODEQL_JAVA_HOME environment variable. - /// - private string? CodeQLJavaHome { get; } - /// /// Value of SEMMLE_DIST environment variable. /// private string? SemmleDist { get; } - public string Distribution => CodeQLExtractorCSharpRoot ?? SemmleDist!; + public string Distribution { get; } - public string JavaHome => CodeQLJavaHome ?? SemmleJavaHome!; - - /// - /// Value of SEMMLE_JAVA_HOME environment variable. - /// - public string? SemmleJavaHome { get; private set; } + public string JavaHome { get; } /// /// Value of SEMMLE_PLATFORM_TOOLS environment variable. /// - public string? SemmlePlatformTools { get; private set; } + public string? SemmlePlatformTools { get; } ///
    /// The absolute path of the odasa executable. diff --git a/csharp/extractor/Semmle.Util/CanonicalPathCache.cs b/csharp/extractor/Semmle.Util/CanonicalPathCache.cs index 8e86907bf0a..bbc8ab995b4 100644 --- a/csharp/extractor/Semmle.Util/CanonicalPathCache.cs +++ b/csharp/extractor/Semmle.Util/CanonicalPathCache.cs @@ -127,8 +127,8 @@ namespace Semmle.Util if (parent != null) { - string? name = Path.GetFileName(path); - string? parentPath = cache.GetCanonicalPath(parent.FullName); + var name = Path.GetFileName(path); + var parentPath = cache.GetCanonicalPath(parent.FullName); try { string[] entries = Directory.GetFileSystemEntries(parentPath, name); From 291df97cd96ae264b7f5a402636baf59ddf7f965 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 31 Mar 2020 17:06:19 +0200 Subject: [PATCH 220/459] C++: Also add InitializeDynamicAllocation instruction for NewArrayExpr --- .../ir/implementation/raw/internal/TranslatedCall.qll | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index a70cf1e45ba..9de3d6efa2b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -397,6 +397,15 @@ class TranslatedNewAllocationSideEffects extends TranslatedAllocationSideEffects } } +class TranslatedNewArrayAllocationSideEffects extends TranslatedAllocationSideEffects { + override NewArrayAllocationExpr expr; + + override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = getTranslatedAllocatorCall(expr).getInstruction(CallTag()) + } +} + class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSideEffects { Call expr; From 97061716f98e0fcc6ae2f46afacd6850dcae3ffb Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 31 Mar 2020 17:10:33 +0200 Subject: [PATCH 221/459] C++: Accept test output --- .../test/library-tests/ir/ir/raw_ir.expected | 166 +++++++++--------- .../ir/ssa/aliased_ssa_ir.expected | 12 +- .../ir/ssa/aliased_ssa_ir_unsound.expected | 13 +- .../ir/ssa/unaliased_ssa_ir.expected | 9 +- .../ir/ssa/unaliased_ssa_ir_unsound.expected | 9 +- .../syntax-zoo/raw_sanity.expected | 1 + 6 files changed, 112 insertions(+), 98 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 06aecc80298..24b67afb9a1 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -4731,85 +4731,93 @@ ir.cpp: # 959| void OperatorNewArray(int) # 959| Block 0 -# 959| v959_1(void) = EnterFunction : -# 959| mu959_2(unknown) = AliasedDefinition : -# 959| mu959_3(unknown) = InitializeNonLocal : -# 959| mu959_4(unknown) = UnmodeledDefinition : -# 959| r959_5(glval) = VariableAddress[n] : -# 959| mu959_6(int) = InitializeParameter[n] : &:r959_5 -# 960| r960_1(glval) = FunctionAddress[operator new[]] : -# 960| r960_2(unsigned long) = Constant[40] : -# 960| r960_3(void *) = Call : func:r960_1, 0:r960_2 -# 960| mu960_4(unknown) = ^CallSideEffect : ~mu959_4 -# 960| r960_5(int *) = Convert : r960_3 -# 961| r961_1(glval) = FunctionAddress[operator new[]] : -# 961| r961_2(glval) = VariableAddress[n] : -# 961| r961_3(int) = Load : &:r961_2, ~mu959_4 -# 961| r961_4(unsigned long) = Convert : r961_3 -# 961| r961_5(unsigned long) = Constant[4] : -# 961| r961_6(unsigned long) = Mul : r961_4, r961_5 -# 961| r961_7(void *) = Call : func:r961_1, 0:r961_6 -# 961| mu961_8(unknown) = ^CallSideEffect : ~mu959_4 -# 961| r961_9(int *) = Convert : r961_7 -# 962| r962_1(glval) = FunctionAddress[operator new[]] : -# 962| r962_2(glval) = VariableAddress[n] : -# 962| r962_3(int) = Load : &:r962_2, ~mu959_4 -# 962| r962_4(unsigned long) = Convert : r962_3 -# 962| r962_5(unsigned long) = Constant[4] : -# 962| r962_6(unsigned long) = Mul : r962_4, r962_5 -# 962| r962_7(float) = Constant[1.0] : -# 962| r962_8(void *) = Call : func:r962_1, 0:r962_6, 1:r962_7 -# 962| mu962_9(unknown) = ^CallSideEffect : ~mu959_4 -# 962| r962_10(int *) = Convert : r962_8 -# 963| r963_1(glval) = FunctionAddress[operator new[]] : -# 963| r963_2(glval) = VariableAddress[n] : -# 963| r963_3(int) = Load : &:r963_2, ~mu959_4 -# 963| r963_4(unsigned long) = Convert : r963_3 -# 963| r963_5(unsigned long) = Constant[8] : -# 963| r963_6(unsigned long) = Mul : r963_4, r963_5 -# 963| r963_7(void *) = Call : func:r963_1, 0:r963_6 -# 963| mu963_8(unknown) = ^CallSideEffect : ~mu959_4 -# 963| r963_9(String *) = Convert : r963_7 -# 964| r964_1(glval) = FunctionAddress[operator new[]] : -# 964| r964_2(glval) = VariableAddress[n] : -# 964| r964_3(int) = Load : &:r964_2, ~mu959_4 -# 964| r964_4(unsigned long) = Convert : r964_3 -# 964| r964_5(unsigned long) = Constant[256] : -# 964| r964_6(unsigned long) = Mul : r964_4, r964_5 -# 964| r964_7(align_val_t) = Constant[128] : -# 964| r964_8(void *) = Call : func:r964_1, 0:r964_6, 1:r964_7 -# 964| mu964_9(unknown) = ^CallSideEffect : ~mu959_4 -# 964| r964_10(Overaligned *) = Convert : r964_8 -# 965| r965_1(glval) = FunctionAddress[operator new[]] : -# 965| r965_2(unsigned long) = Constant[2560] : -# 965| r965_3(align_val_t) = Constant[128] : -# 965| r965_4(float) = Constant[1.0] : -# 965| r965_5(void *) = Call : func:r965_1, 0:r965_2, 1:r965_3, 2:r965_4 -# 965| mu965_6(unknown) = ^CallSideEffect : ~mu959_4 -# 965| r965_7(Overaligned *) = Convert : r965_5 -# 966| r966_1(glval) = FunctionAddress[operator new[]] : -# 966| r966_2(glval) = VariableAddress[n] : -# 966| r966_3(int) = Load : &:r966_2, ~mu959_4 -# 966| r966_4(unsigned long) = Convert : r966_3 -# 966| r966_5(unsigned long) = Constant[1] : -# 966| r966_6(unsigned long) = Mul : r966_4, r966_5 -# 966| r966_7(void *) = Call : func:r966_1, 0:r966_6 -# 966| mu966_8(unknown) = ^CallSideEffect : ~mu959_4 -# 966| r966_9(DefaultCtorWithDefaultParam *) = Convert : r966_7 -# 967| r967_1(glval) = FunctionAddress[operator new[]] : -# 967| r967_2(glval) = VariableAddress[n] : -# 967| r967_3(int) = Load : &:r967_2, ~mu959_4 -# 967| r967_4(unsigned long) = Convert : r967_3 -# 967| r967_5(unsigned long) = Constant[4] : -# 967| r967_6(unsigned long) = Mul : r967_4, r967_5 -# 967| r967_7(void *) = Call : func:r967_1, 0:r967_6 -# 967| mu967_8(unknown) = ^CallSideEffect : ~mu959_4 -# 967| r967_9(int *) = Convert : r967_7 -# 968| v968_1(void) = NoOp : -# 959| v959_7(void) = ReturnVoid : -# 959| v959_8(void) = UnmodeledUse : mu* -# 959| v959_9(void) = AliasedUse : ~mu959_4 -# 959| v959_10(void) = ExitFunction : +# 959| v959_1(void) = EnterFunction : +# 959| mu959_2(unknown) = AliasedDefinition : +# 959| mu959_3(unknown) = InitializeNonLocal : +# 959| mu959_4(unknown) = UnmodeledDefinition : +# 959| r959_5(glval) = VariableAddress[n] : +# 959| mu959_6(int) = InitializeParameter[n] : &:r959_5 +# 960| r960_1(glval) = FunctionAddress[operator new[]] : +# 960| r960_2(unsigned long) = Constant[40] : +# 960| r960_3(void *) = Call : func:r960_1, 0:r960_2 +# 960| mu960_4(unknown) = ^CallSideEffect : ~mu959_4 +# 960| mu960_5(unknown) = ^InitializeDynamicAllocation : &:r960_3 +# 960| r960_6(int *) = Convert : r960_3 +# 961| r961_1(glval) = FunctionAddress[operator new[]] : +# 961| r961_2(glval) = VariableAddress[n] : +# 961| r961_3(int) = Load : &:r961_2, ~mu959_4 +# 961| r961_4(unsigned long) = Convert : r961_3 +# 961| r961_5(unsigned long) = Constant[4] : +# 961| r961_6(unsigned long) = Mul : r961_4, r961_5 +# 961| r961_7(void *) = Call : func:r961_1, 0:r961_6 +# 961| mu961_8(unknown) = ^CallSideEffect : ~mu959_4 +# 961| mu961_9(unknown) = ^InitializeDynamicAllocation : &:r961_7 +# 961| r961_10(int *) = Convert : r961_7 +# 962| r962_1(glval) = FunctionAddress[operator new[]] : +# 962| r962_2(glval) = VariableAddress[n] : +# 962| r962_3(int) = Load : &:r962_2, ~mu959_4 +# 962| r962_4(unsigned long) = Convert : r962_3 +# 962| r962_5(unsigned long) = Constant[4] : +# 962| r962_6(unsigned long) = Mul : r962_4, r962_5 +# 962| r962_7(float) = Constant[1.0] : +# 962| r962_8(void *) = Call : func:r962_1, 0:r962_6, 1:r962_7 +# 962| mu962_9(unknown) = ^CallSideEffect : ~mu959_4 +# 962| mu962_10(unknown) = ^InitializeDynamicAllocation : &:r962_8 +# 962| r962_11(int *) = Convert : r962_8 +# 963| r963_1(glval) = FunctionAddress[operator new[]] : +# 963| r963_2(glval) = VariableAddress[n] : +# 963| r963_3(int) = Load : &:r963_2, ~mu959_4 +# 963| r963_4(unsigned long) = Convert : r963_3 +# 963| r963_5(unsigned long) = Constant[8] : +# 963| r963_6(unsigned long) = Mul : r963_4, r963_5 +# 963| r963_7(void *) = Call : func:r963_1, 0:r963_6 +# 963| mu963_8(unknown) = ^CallSideEffect : ~mu959_4 +# 963| mu963_9(unknown) = ^InitializeDynamicAllocation : &:r963_7 +# 963| r963_10(String *) = Convert : r963_7 +# 964| r964_1(glval) = FunctionAddress[operator new[]] : +# 964| r964_2(glval) = VariableAddress[n] : +# 964| r964_3(int) = Load : &:r964_2, ~mu959_4 +# 964| r964_4(unsigned long) = Convert : r964_3 +# 964| r964_5(unsigned long) = Constant[256] : +# 964| r964_6(unsigned long) = Mul : r964_4, r964_5 +# 964| r964_7(align_val_t) = Constant[128] : +# 964| r964_8(void *) = Call : func:r964_1, 0:r964_6, 1:r964_7 +# 964| mu964_9(unknown) = ^CallSideEffect : ~mu959_4 +# 964| mu964_10(unknown) = ^InitializeDynamicAllocation : &:r964_8 +# 964| r964_11(Overaligned *) = Convert : r964_8 +# 965| r965_1(glval) = FunctionAddress[operator new[]] : +# 965| r965_2(unsigned long) = Constant[2560] : +# 965| r965_3(align_val_t) = Constant[128] : +# 965| r965_4(float) = Constant[1.0] : +# 965| r965_5(void *) = Call : func:r965_1, 0:r965_2, 1:r965_3, 2:r965_4 +# 965| mu965_6(unknown) = ^CallSideEffect : ~mu959_4 +# 965| mu965_7(unknown) = ^InitializeDynamicAllocation : &:r965_5 +# 965| r965_8(Overaligned *) = Convert : r965_5 +# 966| r966_1(glval) = FunctionAddress[operator new[]] : +# 966| r966_2(glval) = VariableAddress[n] : +# 966| r966_3(int) = Load : &:r966_2, ~mu959_4 +# 966| r966_4(unsigned long) = Convert : r966_3 +# 966| r966_5(unsigned long) = Constant[1] : +# 966| r966_6(unsigned long) = Mul : r966_4, r966_5 +# 966| r966_7(void *) = Call : func:r966_1, 0:r966_6 +# 966| mu966_8(unknown) = ^CallSideEffect : ~mu959_4 +# 966| mu966_9(unknown) = ^InitializeDynamicAllocation : &:r966_7 +# 966| r966_10(DefaultCtorWithDefaultParam *) = Convert : r966_7 +# 967| r967_1(glval) = FunctionAddress[operator new[]] : +# 967| r967_2(glval) = VariableAddress[n] : +# 967| r967_3(int) = Load : &:r967_2, ~mu959_4 +# 967| r967_4(unsigned long) = Convert : r967_3 +# 967| r967_5(unsigned long) = Constant[4] : +# 967| r967_6(unsigned long) = Mul : r967_4, r967_5 +# 967| r967_7(void *) = Call : func:r967_1, 0:r967_6 +# 967| mu967_8(unknown) = ^CallSideEffect : ~mu959_4 +# 967| mu967_9(unknown) = ^InitializeDynamicAllocation : &:r967_7 +# 967| r967_10(int *) = Convert : r967_7 +# 968| v968_1(void) = NoOp : +# 959| v959_7(void) = ReturnVoid : +# 959| v959_8(void) = UnmodeledUse : mu* +# 959| v959_9(void) = AliasedUse : ~mu959_4 +# 959| v959_10(void) = ExitFunction : # 970| int designatedInit() # 970| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index c87d2060fb9..2f69b579c30 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -1162,17 +1162,19 @@ ssa.cpp: # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| m248_9(unknown) = ^CallSideEffect : ~m247_10 # 248| m248_10(unknown) = Chi : total:m247_10, partial:m248_9 -# 248| r248_11(char *) = Convert : r248_8 -# 248| m248_12(char *) = Store : &:r248_1, r248_11 +# 248| m248_11(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| m248_12(unknown) = Chi : total:m248_10, partial:m248_11 +# 248| r248_13(char *) = Convert : r248_8 +# 248| m248_14(char *) = Store : &:r248_1, r248_13 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_7 # 249| r249_4(glval) = CopyValue : r249_3 # 249| m249_5(char) = Store : &:r249_4, r249_1 -# 249| m249_6(unknown) = Chi : total:m248_10, partial:m249_5 +# 249| m249_6(unknown) = Chi : total:m248_12, partial:m249_5 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_12 +# 250| r250_3(char *) = Load : &:r250_2, m248_14 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_7 @@ -1185,7 +1187,7 @@ ssa.cpp: # 250| m250_13(unknown) = Chi : total:m249_6, partial:m250_12 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_12 +# 251| r251_3(char *) = Load : &:r251_2, m248_14 # 251| m251_4(char *) = Store : &:r251_1, r251_3 # 247| v247_13(void) = ReturnIndirection : &:r247_8, ~m250_13 # 247| r247_14(glval) = VariableAddress[#return] : diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index b354408d349..e71995247cc 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1154,8 +1154,9 @@ ssa.cpp: # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| m248_9(unknown) = ^CallSideEffect : ~m247_4 # 248| m248_10(unknown) = Chi : total:m247_4, partial:m248_9 -# 248| r248_11(char *) = Convert : r248_8 -# 248| m248_12(char *) = Store : &:r248_1, r248_11 +# 248| m248_11(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| r248_12(char *) = Convert : r248_8 +# 248| m248_13(char *) = Store : &:r248_1, r248_12 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_7 @@ -1164,7 +1165,7 @@ ssa.cpp: # 249| m249_6(unknown) = Chi : total:m247_9, partial:m249_5 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_12 +# 250| r250_3(char *) = Load : &:r250_2, m248_13 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_7 @@ -1174,16 +1175,16 @@ ssa.cpp: # 250| r250_10(void *) = Call : func:r250_1, 0:r250_4, 1:r250_7, 2:r250_9 # 250| v250_11(void) = ^SizedBufferReadSideEffect[1] : &:r250_7, r250_9, ~m249_6 # 250| m250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9 -# 250| m250_13(unknown) = Chi : total:m248_10, partial:m250_12 +# 250| m250_13(unknown) = Chi : total:m248_11, partial:m250_12 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_12 +# 251| r251_3(char *) = Load : &:r251_2, m248_13 # 251| m251_4(char *) = Store : &:r251_1, r251_3 # 247| v247_12(void) = ReturnIndirection : &:r247_8, m249_6 # 247| r247_13(glval) = VariableAddress[#return] : # 247| v247_14(void) = ReturnValue : &:r247_13, m251_4 # 247| v247_15(void) = UnmodeledUse : mu* -# 247| v247_16(void) = AliasedUse : ~m250_13 +# 247| v247_16(void) = AliasedUse : ~m248_10 # 247| v247_17(void) = ExitFunction : # 254| char StringLiteralAliasing2(bool) diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index cbaf532bffa..1e6551dd15a 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -1074,8 +1074,9 @@ ssa.cpp: # 248| r248_7(unsigned long) = Mul : r248_5, r248_6 # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| mu248_9(unknown) = ^CallSideEffect : ~mu247_4 -# 248| r248_10(char *) = Convert : r248_8 -# 248| m248_11(char *) = Store : &:r248_1, r248_10 +# 248| mu248_10(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| r248_11(char *) = Convert : r248_8 +# 248| m248_12(char *) = Store : &:r248_1, r248_11 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_6 @@ -1083,7 +1084,7 @@ ssa.cpp: # 249| mu249_5(char) = Store : &:r249_4, r249_1 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_11 +# 250| r250_3(char *) = Load : &:r250_2, m248_12 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_6 @@ -1095,7 +1096,7 @@ ssa.cpp: # 250| mu250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_11 +# 251| r251_3(char *) = Load : &:r251_2, m248_12 # 251| m251_4(char *) = Store : &:r251_1, r251_3 # 247| v247_11(void) = ReturnIndirection : &:r247_7, ~mu247_4 # 247| r247_12(glval) = VariableAddress[#return] : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index cbaf532bffa..1e6551dd15a 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -1074,8 +1074,9 @@ ssa.cpp: # 248| r248_7(unsigned long) = Mul : r248_5, r248_6 # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| mu248_9(unknown) = ^CallSideEffect : ~mu247_4 -# 248| r248_10(char *) = Convert : r248_8 -# 248| m248_11(char *) = Store : &:r248_1, r248_10 +# 248| mu248_10(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| r248_11(char *) = Convert : r248_8 +# 248| m248_12(char *) = Store : &:r248_1, r248_11 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_6 @@ -1083,7 +1084,7 @@ ssa.cpp: # 249| mu249_5(char) = Store : &:r249_4, r249_1 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_11 +# 250| r250_3(char *) = Load : &:r250_2, m248_12 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_6 @@ -1095,7 +1096,7 @@ ssa.cpp: # 250| mu250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_11 +# 251| r251_3(char *) = Load : &:r251_2, m248_12 # 251| m251_4(char *) = Store : &:r251_1, r251_3 # 247| v247_11(void) = ReturnIndirection : &:r247_7, ~mu247_4 # 247| r247_12(glval) = VariableAddress[#return] : diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 082bbafa0f1..cd5366a0c73 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -49,6 +49,7 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| CPP-309.cpp:7:5:7:20 | InitializeDynamicAllocation: new[] | | VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | | VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | | VacuousDestructorCall.cpp:4:3:4:3 | Load: y | From 60d5ed9c79dbbd55050a10d9249259e3690cde08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Tue, 31 Mar 2020 18:30:00 +0200 Subject: [PATCH 222/459] Input from Review --- .../ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp | 2 -- java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp index d3113576b6d..e9cc9a0ebb2 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp @@ -23,12 +23,10 @@ is called on the URL, potentially leading to a local file access.

    -
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql index 3b8dff2ac09..702e11b8740 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql @@ -17,8 +17,8 @@ class URLConstructor extends ClassInstanceExpr { Expr stringArg() { // Query only in URL's that were constructed by calling the single parameter string constructor. this.getConstructor().getNumberOfParameters() = 1 and - this.getConstructor().getParameter(0).getType() instanceof TypeString - and result = this.getArgument(0) + this.getConstructor().getParameter(0).getType() instanceof TypeString and + result = this.getArgument(0) } } From f430cf9d189763c01bc69b07ebfb437b7597effb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 31 Mar 2020 18:10:41 +0100 Subject: [PATCH 223/459] C++: Use hasGlobalName. --- .../src/semmle/code/cpp/models/implementations/Allocation.qll | 2 +- .../src/semmle/code/cpp/models/implementations/Deallocation.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index 1454f64f509..ad26086998a 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -223,7 +223,7 @@ class SizelessAllocationFunction extends AllocationFunction { class OperatorNewAllocationFunction extends AllocationFunction { OperatorNewAllocationFunction() { exists(string name | - hasGlobalOrStdName(name) and + hasGlobalName(name) and ( // operator new(bytes, ...) name = "operator new" or diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 35aa5c2227a..f94800f657d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -87,7 +87,7 @@ class StandardDeallocationFunction extends DeallocationFunction { class OperatorDeleteDeallocationFunction extends DeallocationFunction { OperatorDeleteDeallocationFunction() { exists(string name | - hasGlobalOrStdName(name) and + hasGlobalName(name) and ( // operator delete(pointer, ...) name = "operator delete" or From f06ae6e9defb8d36260466f4d1f49a6a0022fad0 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 31 Mar 2020 19:49:04 +0200 Subject: [PATCH 224/459] C++: Accept more test output --- .../dataflow/security-taint/tainted_diff.expected | 6 ------ .../dataflow/security-taint/tainted_ir.expected | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected index d89a1de6c86..26441b08ba4 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected @@ -14,12 +14,6 @@ | test.cpp:100:12:100:15 | call to gets | test.cpp:100:2:100:8 | pointer | AST only | | test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | AST only | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | IR only | -| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only | | test.cpp:106:28:106:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only | | test.cpp:106:28:106:33 | call to getenv | test.cpp:108:8:108:11 | copy | AST only | | test.cpp:106:28:106:33 | call to getenv | test.cpp:109:9:109:12 | copy | AST only | -| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... | AST only | -| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp | AST only | -| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... | AST only | -| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... | AST only | -| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected index bed6881cc5f..50c90bccb2b 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected @@ -57,9 +57,15 @@ | test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | | | test.cpp:106:28:106:33 | call to getenv | test.cpp:11:36:11:37 | s2 | | | test.cpp:106:28:106:33 | call to getenv | test.cpp:106:17:106:24 | userName | | | test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:33 | call to getenv | | | test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:46 | (const char *)... | | | test.cpp:106:28:106:33 | call to getenv | test.cpp:109:2:109:7 | call to strcpy | | | test.cpp:106:28:106:33 | call to getenv | test.cpp:109:15:109:22 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy | | From b579e6aabe3c78366572f9b75e57a1d44a2f258a Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 31 Mar 2020 12:56:52 -0700 Subject: [PATCH 225/459] C++: accept consistency test output --- .../library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected index 1e78ae87f40..517ef7099c0 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected @@ -1,6 +1,7 @@ missingOperand unexpectedOperand duplicateOperand +| ssa.cpp:286:27:286:30 | ReturnIndirection: argv | Instruction has 2 operands with tag 'SideEffect' in function '$@'. | ssa.cpp:286:5:286:8 | IR: main | int main(int, char**) | missingPhiOperand missingOperandType duplicateChiOperand @@ -19,6 +20,7 @@ switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated invalidOverlap +| ssa.cpp:286:27:286:30 | SideEffect | MemoryOperand 'SideEffect' has a `getDefinitionOverlap()` of 'MayPartiallyOverlap'. | ssa.cpp:286:5:286:8 | IR: main | int main(int, char**) | missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType From 42388b0d974d8722cf0f7dd1f46fe6ea0706d9a4 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 31 Mar 2020 22:11:58 -0700 Subject: [PATCH 226/459] Python: ObjectAPI to ValueAPI: ReturnValueIgnored: Adds prototype version of getAnInferredReturnType --- python/ql/src/Functions/ReturnValueIgnored.ql | 2 +- python/ql/src/semmle/python/objects/ObjectAPI.qll | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index e3b1ccd1dbe..3773fabd40d 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -42,7 +42,7 @@ predicate returns_meaningful_value(FunctionValue f) { or /* Is f a builtin function that returns something other than None? * Ignore __import__ as it is often called purely for side effects */ - f.isBuiltin() and f.getAnInferredReturnType() != theNoneType() and not f.getName() = "__import__" + f.isBuiltin() and f.getAnInferredReturnType() != ClassValue::nonetype() and not f.getName() = "__import__" ) } diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 29e5650666f..9fba3a668de 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -514,6 +514,12 @@ abstract class FunctionValue extends CallableValue { predicate isOverriddenMethod() { exists(Value f | f.overrides(this)) } + + /** Gets a class that this function may return */ + ClassValue getAnInferredReturnType() { + //result = this.(BuiltinCallable).getAReturnType() + result = this.getScope().getAReturnValueFlowNode().pointsTo().getClass() + } } /** Class representing Python functions */ From 0b2db56051c40de8496c5e4dbdaaf4774e8f94dd Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 31 Mar 2020 22:15:21 -0700 Subject: [PATCH 227/459] Python: ObjectAPI to ValueAPI: ObjectAPI.qll: Fixes error in isIterator --- python/ql/src/semmle/python/objects/ObjectAPI.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index e467bb2aa0b..61856ffe18b 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -423,7 +423,7 @@ class ClassValue extends Value { * '__next__' method exists to define a class as an iterator. */ major_version() = 2 and this.hasAttribute("next") and - exists(ClassObject other, FunctionObject iter | + exists(ClassValue other, FunctionValue iter | other.declaredAttribute("__iter__") = iter | iter.getAnInferredReturnType() = this ) From eab31d3bef2dd22a8c3ebed32164e04118d04afa Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 31 Mar 2020 23:34:17 -0700 Subject: [PATCH 228/459] Python: ObjectAPI to ValueAPI: SignatureOverriddenMethod: Updates expected results --- .../Functions/general/SignatureOverriddenMethod.expected | 4 ++-- .../Functions/overriding/SignatureOverriddenMethod.expected | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected b/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected index f23936e6a42..81c45ab8abe 100644 --- a/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected +++ b/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected @@ -1,2 +1,2 @@ -| om_test.py:32:5:32:35 | Function grossly_wrong1 | Overriding method 'grossly_wrong1' has signature mismatch with $@. | om_test.py:12:5:12:41 | Function grossly_wrong1 | overridden method | -| om_test.py:35:5:35:47 | Function grossly_wrong2 | Overriding method 'grossly_wrong2' has signature mismatch with $@. | om_test.py:15:5:15:41 | Function grossly_wrong2 | overridden method | +| om_test.py:32:5:32:35 | Function Derived.grossly_wrong1 | Overriding method 'grossly_wrong1' has signature mismatch with $@. | om_test.py:12:5:12:41 | Function Base.grossly_wrong1 | overridden method | +| om_test.py:35:5:35:47 | Function Derived.grossly_wrong2 | Overriding method 'grossly_wrong2' has signature mismatch with $@. | om_test.py:15:5:15:41 | Function Base.grossly_wrong2 | overridden method | diff --git a/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected b/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected index 99f0fb667d6..bcb9363a55a 100644 --- a/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected +++ b/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected @@ -1 +1 @@ -| test.py:30:5:30:26 | Function meth3 | Overriding method 'meth3' has signature mismatch with $@. | test.py:11:5:11:20 | Function meth3 | overridden method | +| test.py:30:5:30:26 | Function Derived.meth3 | Overriding method 'meth3' has signature mismatch with $@. | test.py:11:5:11:20 | Function Base.meth3 | overridden method | From 093eb714332b4c5d6b32fa308d73986c6f26a58d Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 1 Apr 2020 00:17:12 -0700 Subject: [PATCH 229/459] Python: ObjectAPI to ValueAPI: ReturnValueIgnored: Adds getAReturnType --- .../src/semmle/python/objects/ObjectAPI.qll | 37 ++++++++++++++++++- .../return_values/ReturnValueIgnored.expected | 2 +- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 9fba3a668de..ce4f0e6d545 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -517,8 +517,9 @@ abstract class FunctionValue extends CallableValue { /** Gets a class that this function may return */ ClassValue getAnInferredReturnType() { - //result = this.(BuiltinCallable).getAReturnType() - result = this.getScope().getAReturnValueFlowNode().pointsTo().getClass() + result = this.(BuiltinFunctionValue).getAReturnType() + or + result = this.(BuiltinMethodValue).getAReturnType() } } @@ -575,6 +576,29 @@ class BuiltinFunctionValue extends FunctionValue { override int maxParameters() { none() } + + ClassValue getAReturnType() { + /* Enumerate the types of a few builtin functions, that the CPython analysis misses. + */ + this = TBuiltinFunctionObject(Builtin::builtin("hex")) and result = ClassValue::str() + or + this = TBuiltinFunctionObject(Builtin::builtin("oct")) and result = ClassValue::str() + or + this = TBuiltinFunctionObject(Builtin::builtin("intern")) and result = ClassValue::str() + or + /* Fix a few minor inaccuracies in the CPython analysis */ + exists(Builtin mthd, Builtin cls | this = TBuiltinFunctionObject(mthd) and result = TBuiltinClassObject(cls) + | ext_rettype(mthd, cls)) and + not ( + this = TBuiltinFunctionObject(Builtin::builtin("__import__")) and result = ClassValue::nonetype() + or + this = TBuiltinFunctionObject(Builtin::builtin("compile")) and result = ClassValue::nonetype() + or + this = TBuiltinFunctionObject(Builtin::builtin("sum")) + or + this = TBuiltinFunctionObject(Builtin::builtin("filter")) + ) + } } /** Class representing builtin methods, such as `list.append` or `set.add` */ @@ -600,6 +624,15 @@ class BuiltinMethodValue extends FunctionValue { none() } + ClassValue getAReturnType() { + exists(Builtin mthd, Builtin cls | + this = TBuiltinMethodObject(mthd) and + result = TBuiltinClassObject(cls) + | + ext_rettype(mthd, cls) + ) + } + } /** A class representing sequence objects with a length and tracked items. diff --git a/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected b/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected index 60640bb96ba..c2a8e8ee573 100644 --- a/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected +++ b/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected @@ -1,3 +1,3 @@ | functions_test.py:159:5:159:9 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | functions_test.py:12:1:12:11 | Function ok2 | ok2 | | functions_test.py:160:5:160:9 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | functions_test.py:36:1:36:11 | Function ok4 | ok4 | -| functions_test.py:161:5:161:17 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | file://:Compiled Code:0:0:0:0 | Builtin-function sorted | sorted | +| functions_test.py:161:5:161:17 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | file://:0:0:0:0 | Builtin-function sorted | sorted | From f8f51109d073f7cd4c72e3e0b542bd1897aff657 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 1 Apr 2020 12:07:19 +0200 Subject: [PATCH 230/459] Python: Add missing ` in qldoc --- python/ql/src/semmle/python/objects/ObjectAPI.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 9d9d7cb0bbc..61e3f17c5d7 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -415,7 +415,7 @@ class ClassValue extends Value { * ``` * `this.lookup("f")` is equivalent to `C.__dict__['f']`, which is the class-method * whereas - * `this.attr("f") is equivalent to `C.f`, which is a bound-method. + * `this.attr("f")` is equivalent to `C.f`, which is a bound-method. */ Value lookup(string name) { this.(ClassObjectInternal).lookup(name, result, _) } From 51f4575479728b29fab45a76876a978992ac9351 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 1 Apr 2020 11:40:07 +0100 Subject: [PATCH 231/459] Include spec and "About QL" in reference sphinx project --- .../ql-handbook/about-the-ql-language.rst | 70 + docs/language/ql-handbook/index.rst | 34 +- docs/language/ql-handbook/language.rst | 2017 +++++++++++++++++ docs/language/ql-handbook/qldoc.rst | 50 + 4 files changed, 2144 insertions(+), 27 deletions(-) create mode 100644 docs/language/ql-handbook/about-the-ql-language.rst create mode 100644 docs/language/ql-handbook/language.rst create mode 100644 docs/language/ql-handbook/qldoc.rst diff --git a/docs/language/ql-handbook/about-the-ql-language.rst b/docs/language/ql-handbook/about-the-ql-language.rst new file mode 100644 index 00000000000..72e6209f2e6 --- /dev/null +++ b/docs/language/ql-handbook/about-the-ql-language.rst @@ -0,0 +1,70 @@ +About the QL language +###################### + +QL is the powerful query language that underlies CodeQL, which is used to analyze code. + +For more information about the important concepts and syntactic constructs of QL, see the individual reference topics such as :doc:`Predicates ` and :doc:`Types `. +The explanations and examples help you understand how the language works, and how to write more advanced QL code. + +For formal specifications of the QL language and QLDoc comments, see the :doc:`QL language specification ` and :doc:`QLDoc comment specification `. + +About query languages and databases +----------------------------------- + +This section is aimed at users with a background in general purpose programming as well as in databases. For a basic introduction and information on how to get started, see `Learning CodeQL `__. + +QL is a declarative, object-oriented query language that is optimized to enable efficient analysis of hierarchical data structures, in particular, databases representing software artifacts. + +A database is an organized collection of data. The most commonly used database model is a relational model which stores data in tables and SQL (Structured Query Language) is the most commonly used query language for relational databases. + +The purpose of a query language is to provide a programming platform where you can ask questions about information stored in a database. A database management system manages the storage and administration of data and provides the querying mechanism. A query typically refers to the relevant database entities and specifies various conditions (called predicates) that must be satisfied by the results. Query evaluation involves checking these predicates and generating the results. Some of the desirable properties of a good query language and its implementation include: + +- Declarative specifications - a declarative specification describes properties that the result must satisfy, rather than providing the procedure to compute the result. In the context of database query languages, declarative specifications abstract away the details of the underlying database management system and query processing techniques. This greatly simplifies query writing. +- Expressiveness - a powerful query language allows you to write complex queries. This makes the language widely applicable. +- Efficient execution - queries can be complex and databases can be very large, so it is crucial for a query language implementation to process and execute queries efficiently. + +Properties of QL +---------------- + +The syntax of QL is similar to SQL, but the semantics of QL are based on Datalog, a declarative logic programming language often used as a query language. This makes QL primarily a logic language, and all operations in QL are logical operations. Furthermore, QL inherits recursive predicates from Datalog, and adds support for aggregates, making even complex queries concise and simple. For example, consider a database containing parent-child relationships for people. If we want to find the number of descendants of a person, typically we would: + +#. Find a descendant of the given person, that is, a child or a descendant of a child. +#. Count the number of descendants found using the previous step. + +When you write this process in QL, it closely resembles the above structure. Notice that we used recursion to find all descendants of the given person, and an aggregate to count the number of descendants. Translating these steps into the final query without adding any procedural details is possible due to the declarative nature of the language. The QL code would look something like this: + +.. code-block:: ql + + Person getADescendant(Person p) { + result = p.getAChild() or + result = getADescendant(p.getAChild()) + } + + int getNumberOfDescendants(Person p) { + result = count(getADescendant(p)) + } + +QL and object orientation +------------------------- + +Object orientation is an important feature of QL. The benefits of object orientation are well known – it increases modularity, enables information hiding, and allows code reuse. QL offers all these benefits without compromising on its logical foundation. This is achieved by defining a simple object model where classes are modeled as predicates and inheritance as implication. The libraries made available for all supported languages make extensive use of classes and inheritance. + +QL and general purpose programming languages +-------------------------------------------- + +Here are a few prominent conceptual and functional differences between general purpose programming languages and QL: + +- QL does not have any imperative features such as assignments to variables or file system operations. +- QL operates on sets of tuples and a query can be viewed as a complex sequence of set operations that defines the result of the query. +- QL's set-based semantics makes it very natural to process collections of values without having to worry about efficiently storing, indexing and traversing them. +- In object oriented programming languages, instantiating a class involves creating an object by allocating physical memory to hold the state of that instance of the class. In QL, classes are just logical properties describing sets of already existing values. + +Further reading +--------------- + +Academic references available from the `Semmle website `__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: + +- `Database theory: Query languages `__ +- `Logic Programming and Databases book - Amazon page `__ +- `Foundations of Databases `__ +- `Datalog `__ \ No newline at end of file diff --git a/docs/language/ql-handbook/index.rst b/docs/language/ql-handbook/index.rst index a1e28bbaec4..ec4ab6d671e 100644 --- a/docs/language/ql-handbook/index.rst +++ b/docs/language/ql-handbook/index.rst @@ -1,28 +1,12 @@ -QL language handbook -#################### +QL language reference +##################### -Welcome to the QL language handbook! - -This document describes the main features of the QL language. The explanations and examples -help you understand how the language works, and how to write more advanced QL code. - -Each section describes an important concept or syntactic construct of QL. For an overview, see -the table of contents below. - -If you are just getting started with QL, see `Learning CodeQL `_ -for a list of the available resources. - -.. index:: specification - -For a formal specification of the QL language, see the `QL language specification -`_. - -Table of contents -***************** +Learn all about QL, the powerful query language that underlies the code scanning tool CodeQL. .. toctree:: - :maxdepth: 3 + :maxdepth: 1 + about-the-ql-language predicates queries types @@ -36,9 +20,5 @@ Table of contents lexical-syntax name-resolution evaluation - -Index and search -**************** - -* :ref:`genindex` -* :ref:`search` \ No newline at end of file + language + qldoc \ No newline at end of file diff --git a/docs/language/ql-handbook/language.rst b/docs/language/ql-handbook/language.rst new file mode 100644 index 00000000000..5bb7370d11c --- /dev/null +++ b/docs/language/ql-handbook/language.rst @@ -0,0 +1,2017 @@ +QL language specification +========================= + +This is a formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. + +.. This ``highlight`` directive prevents code blocks in this file being highlighted as QL (the default language for this Sphinx project). + +.. highlight:: none + +Introduction +------------ + +QL is a query language for CodeQL databases. The data is relational: named relations hold sets of tuples. The query language is a dialect of Datalog, using stratified semantics, and it includes object-oriented classes. + +Notation +-------- + +This section describes the notation used in the specification. + +Unicode characters +~~~~~~~~~~~~~~~~~~ + +Unicode characters in this document are described in two ways. One is to supply the character inline in the text, between double quote marks. The other is to write a capital U, followed by a plus sign, followed by a four-digit hexadecimal number representing the character's code point. As an example of both, the first character in the name QL is "Q" (U+0051). + +Grammars +~~~~~~~~ + +The syntactic forms of QL constructs are specified using a modified Backus-Naur Form (BNF). Syntactic forms, including classes of tokens, are named using bare identifiers. Quoted text denotes a token by its exact sequence of characters in the source code. + +BNF derivation rules are written as an identifier naming the syntactic element, followed by ``::=``, followed by the syntax itself. + +In the syntax itself, juxtaposition indicates sequencing. The vertical bar (``|``, U+007C) indicates alternate syntax. Parentheses indicate grouping. An asterisk (``*``, U+002A) indicates repetition zero or more times, and a plus sign (``+``, U+002B) indicates repetition one or more times. Syntax followed by a question mark (``?``, U+003F) indicates zero or one occurrences of that syntax. + +Architecture +------------ + +A *QL program* consists of a query module defined in a QL file and a number of library modules defined in QLL files that it imports (see `Import directives <#import-directives>`__). The module in the QL file includes one or more queries (see `Queries <#queries>`__). A module may also include *import directives* (see `Import directives <#import-directives>`__), non-member predicates (see `Non-member predicates <#non-member-predicates>`__), class definitions (see `Classes <#classes>`__), and module definitions (see `Modules <#modules>`__). + +QL programs are interpreted in the context of a *database* and a *library path* . The database provides a number of definitions: database types (see `Types <#types>`__), entities (see `Values <#values>`__), built-in predicates (see `Built-ins <#built-ins>`__), and the *database content* of built-in predicates and external predicates (see `Evaluation <#evaluation>`__). The library path is a sequence of file-system directories that hold QLL files. + +A QL program can be *evaluated* (see `Evaluation <#evaluation>`__) to produce a set of tuples of values (see `Values <#values>`__). + +For a QL program to be *valid*, it must conform to a variety of conditions that are described throughout this specification; otherwise the program is said to be *invalid*. An implementation of QL must detect all invalid programs and refuse to evaluate them. + +Name resolution +--------------- + +All modules have three environments that dictate name resolution. These are multimaps of keys to declarations. + +The environments are: + +- The *module environment*, whose keys are module names and whose values are modules. +- The *type environment*, whose keys are type names and whose values are types. +- The *predicate environment*, whose keys are pairs of predicate names and arities and whose values are predicates. + +If not otherwise specified, then the environment for a piece of syntax is the same as the environment of its enclosing syntax. + +When a key is resolved in an environment, if there is no value for that key, then the program is invalid. + +Environments may be combined as follows: + +- *Union*. This takes the union of the entry sets of the two environments. +- *Overriding union*. This takes the union of two environments, but if there are entries for a key in the first map, then no additional entries for that key are included from the second map. + +A *definite* environment has at most one entry for each key. Resolution is unique in a definite environment. + +Global environments +~~~~~~~~~~~~~~~~~~~ + +The global module environment is empty. + +The global type environment has entries for the primitive types ``int``, ``float``, ``string``, ``boolean``, and ``date``, as well as any types defined in the database schema. + +The global predicate environment includes all the built-in classless predicates, as well as any extensional predicates declared in the database schema. + +The program is invalid if any of these environments is not definite. + +Module environments +~~~~~~~~~~~~~~~~~~~ + +For each of modules, types, and predicates, a module *imports*, *declares*, and *exports* an environment. These are defined as follows (with X denoting the type of entity we are currently considering): + +- The *imported X environment* of a module is defined to be the union of the exported X environments of all the modules which the current module directly imports (see `Import directives <#import-directives>`__). + +- The *declared X environment* of a module is the multimap of X declarations in the module itself. + +- The *exported X environment* of a module is the union of the exported X environments of the modules which the current module directly imports (excluding ``private`` imports), and the declared X environment of the current module (excluding ``private`` declarations). + +- The *external X environment* of a module is the visible X environment of the enclosing module, if there is one, and otherwise the global X environment. + +- The *visible X environment* is the union of the imported X environment, the declared X environment, and the external X environment. + +The program is invalid if any of these environments is not definite. + +Module definitions may be recursive, so the module environments are defined as the least fixed point of the operator given by the above definition. Since all the operations involved are monotonic, this fixed point exists and is unique. + +Modules +------- + +Module definitions +~~~~~~~~~~~~~~~~~~ + +A QL module definition has the following syntax: + +:: + + module ::= annotation* "module" modulename "{" moduleBody "}" + + moduleBody ::= (import | predicate | class | module | alias | select)* + +A module definition extends the current module's declared module environment with a mapping from the module name to the module definition. + +QL files consist of simply a module body without a name and surrounding braces: + +:: + + ql ::= moduleBody + +QL files define a module corresponding to the file, whose name is the same as the filename. + +Kinds of modules +~~~~~~~~~~~~~~~~ + +A module may be: + +- A *file module*, if it is defined implicitly by a QL file. +- A *query module*, if it is defined by a QL file. +- A *library module*, if it is not a query module. + +A query module must contain one or more queries. + +Import directives +~~~~~~~~~~~~~~~~~ + +An import directive refers to a module identifier: + +:: + + import ::= annotations "import" importModuleId ("as" modulename)? + + qualId ::= simpleId | qualId "." simpleId + + importModuleId ::= qualId + | importModuleId "::" simpleId + +An import directive may optionally name the imported module using an ``as`` declaration. If a name is defined, then the import directive adds to the declared module environment of the current module a mapping from the name to the declaration of the imported module. Otherwise, the current module *directly imports* the imported module. + +Module resolution +~~~~~~~~~~~~~~~~~ + +Module identifiers are resolved to modules as follows. + +For simple identifiers: + +- First, the identifier is resolved as a one-segment qualified identifier (see below). + +- If this fails, the identifier is resolved in the current module's visible module environment. + +For selection identifiers (``a::b``): + +- The qualifier of the selection (``a``) is resolved as a module, and then the name (``b``) is resolved in the exported module environment of the qualifier module. + +For qualified identifiers (``a.b``): + +- Define the *current file* as the file the import directive occurs in. + +- Determine the current file's *query directory*, if any. Starting with the directory containing the current file, and walking up the directory structure, each directory is checked for a file called ``queries.xml``, containing a single top-level tag named ``queries``, which has a ``language`` attribute set to the identifier of the active database scheme (for example, ````). The closest enclosing directory is taken as the current file's query directory. + +- Build up a list of *candidate search paths*, consisting of the current file's directory, the current file's query directory (if one was determined in the previous step), and the list of directories making up the library path (in order). + +- Determine the first candidate search path that has a *matching* QLL file for the import directive's qualified name. A QLL file in a candidate search path is said to match a qualified name if, starting from the candidate search path, there is a subdirectory for each successive qualifier in the qualified name, and the directory named by the final qualifier contains a file whose base name matches the qualified name's base name, with the addition of the file extension ``.qll``. The file and directory names are matched case-sensitively, regardless of whether the filesystem is case-sensitive or not. + +- The resolved module is the module defined by the selected candidate search path. + +A qualified module identifier is only valid within an import. + +Module references and active modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A module ``M`` *references* another module ``N`` if any of the following holds: + +- ``M`` imports ``N``. +- ``M`` defines ``N``. +- ``N`` is ``M``'s enclosing module. + +In a QL program, the *active* modules are the modules which are referenced transitively by the query module. + +Types +----- + +QL is a typed language. This section specifies the kinds of types available, their attributes, and the syntax for referring to them. + +Kinds of types +~~~~~~~~~~~~~~ + +Types in QL are either *primitive* types, *database* types, *class* types, *character* types or *class domain* types. + +The primitive types are ``boolean``, ``date``, ``float``, ``int``, and ``string``. + +Database types are supplied as part of the database. Each database type has a *name*, which is an identifier starting with an at sign (``@``, U+0040) followed by lower-case letter. Database types have some number of *base types*, which are other database types. In a valid database, the base types relation is non-cyclic. + +Class types are defined in QL, in a way specified later in this document (see `Classes <#classes>`__). Each class type has a name that is an identifier starting with an upper-case letter. Each class type has one or more base types, which can be any kind of type except a class domain type. A class type may be declared *abstract*. + +Any class in QL has an associated class domain type and an associated character type. + +Within the specification the class type for ``C`` is written ``C.class``, the character type is written ``C.C`` and the domain type is written ``C.extends``. However the class type is still named ``C``. + +Type references +~~~~~~~~~~~~~~~ + +With the exception of class domain types and character types (which cannot be referenced explicitly in QL source), a reference to a type is written as the name of the type. In the case of database types, the name includes the at sign (``@``, U+0040). + +:: + + type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" + + moduleId ::= simpleId | moduleId "::" simpleId + +A type reference is resolved to a type as follows: + +- If it is a selection identifier (for example, ``a::B``), then the qualifier (``a``) is resolved as a module (see `Module resolution <#module-resolution>`__). The identifier (``B``) is then resolved in the exported type environment of the qualifier module. + +- Otherwise, the identifier is resolved in the current module's visible type environment. + +Relations among types +~~~~~~~~~~~~~~~~~~~~~ + +Types are in a subtype relationship with each other. Type A is a *subtype* of type B if one of the following is true: + +- A and B are the same type. + +- There is some type C, where A is a subtype of C and C is a subtype of B. + +- A and B are database types, and B is a base type of A. + +- A is the character type of C, and B is the class domain type of C. + +- A is a class type, and B is the character type of A. + +- A is a class domain type, and B is a base type of the associated class type. + +- A is ``int`` and B is ``float``. + +Supertypes are the converse of subtypes: A is a *supertype* of B if B is a subtype of A. + +Types A and B are *compatible* with each other if they either have a common supertype, or they each have some supertype that is a database type. + +Typing environments +~~~~~~~~~~~~~~~~~~~ + +A *typing environment* is a finite map of variables to types. Each variable in the map is either an identifier or one of two special symbols: ``this``, and ``result``. + +Most forms of QL syntax have a typing environment that applies to them. That typing environment is determined by the context the syntax appears in. + +Note that this is distinct from the type environment, which is a map from type names to types. + +Active types +~~~~~~~~~~~~ + +In a QL program, the *active* types are those defined in active modules. In the remainder of this specification, any reference to the types in the program refers only to the active types. + +Values +------ + +Values are the fundamental data that QL programs compute over. This section specifies the kinds of values available in QL, specifies the sorting order for them, and describes how values can be combined into tuples. + +Kinds of values +~~~~~~~~~~~~~~~ + +There are six kinds of values in QL: one kind for each of the five primitive types, and *entities*. Each value has a type. + +A boolean value is of type ``boolean``, and may have one of two distinct values: ``true`` or ``false``. + +A date value is of type ``date``. It encodes a time and a date in the Gregorian calendar. Specifically, it includes a year, a month, a day, an hour, a minute, a second, and a millisecond, each of which are integers. The year ranges from -16777216 to 16777215, the month from 0 to 11, the day from 1 to 31, the hour from 0 to 23, the minutes from 0 to 59, the seconds from 0 to 59, and the milliseconds from 0 to 999. + +A float value is of type ``float``. Each float value is a binary 64-bit floating-point value as specified in IEEE 754. + +An integer value is of type ``int``. Each value is a 32-bit two's complement integer. + +A string is a finite sequence of 16-bit characters. The characters are interpreted as Unicode code points. + +The database includes a number of opaque entity values. Each such value has a type that is one of the database types, and an identifying integer. An entity value is written as the name of its database type followed by its identifying integer in parentheses. For example, ``@tree(12)``, ``@person(16)``, and ``@location(38132)`` are entity values. The identifying integers are left opaque to programmers in this specification, so an implementation of QL is free to use some other set of countable labels to identify its entities. + +Ordering +~~~~~~~~ + +Values in general do not have a specified ordering. In particular, entity values have no specified ordering with entities or any other values. Primitive values, however, have a total ordering with other primitive values in the same type. Primitives types and their subtypes are said to be *orderable*. + +For booleans, ``false`` is ordered before ``true``. + +For dates, the ordering is chronological. + +For floats, the ordering is as specified in IEEE 754 when one exists, except that NaN is considered equal to itself and is ordered after all other floats, and negative zero is considered to be strictly less than positive zero. + +For integers, the ordering is as for two's complement integers. + +For strings, the ordering is lexicographic. + +Tuples +~~~~~~ + +Values can be grouped into tuples in two different ways. + +An *ordered tuple* is a finite, ordered sequence of values. For example, (``1``, ``2``, ``"three"``) is an ordered sequence of two integers and a string. + +A *named tuple* is a finite map of variables to values. Each variable in a named tuple is either an identifier, ``this``, or ``result``. + +A *variable declaration list* provides a sequence of variables and a type for each one: + +:: + + var_decls ::= var_decl ("," var_decl)* + var_decl ::= type simpleId + +A valid variable declaration list must not include two declarations with the same variable name. Moreover, if the declaration has a typing environment that applies, it must not use a variable name that is already present in that typing environment. + +An *extension* of a named tuple for a given variable declaration list is a named tuple that additionally maps each variable in the list to a value. The value mapped by each new variable must be in the type that is associated with that variable in the given list; see `The store <#the-store>`__ for the definition of a value being in a type. + +The store +--------- + +QL programs evaluate in the context of a *store*. This section specifies several definitions related to the store. + +A *fact* is a predicate or type along with an ordered tuple. A fact is written as the predicate name or type name followed immediately by the tuple. Here are some examples of facts: + +:: + + successor(0, 1) + Tree.toString(@method_tree(12), "def println") + Location.class(@location(43)) + Location.getURL(@location(43), "file:///etc/hosts:2:0:2:12") + +A *store* is a mutable set of facts. The store can be mutated by adding more facts to it. + +An ordered tuple *directly satisfies* a predicate or type with a given if there is a fact in the store with the given tuple and predicate or type. + +A value ``v`` is in a type ``t`` under any of the following conditions: + +- The type of ``v`` is ``t`` and ``t`` is a primitive type. +- The tuple ``(v)`` directly satisfies ``t``. + +An ordered tuple *satisfies a predicate* ``p`` under the following circumstances. If ``p`` is not a member predicate, then the tuple satisfies the predicate whenever it directly satisfies the predicate. + +Otherwise, the tuple must be the tuple of a fact in the store with predicate ``q``, where ``q`` has the same root definition as ``p``. The first element of the tuple must be in the type before the dot in ``q``, and there must be no other predicate that overrides ``q`` such that this is true (see `Classes <#classes>`__ for details on overriding and root definitions). + +An ordered tuple ``(a0, an)`` satisfies the ``+`` closure of a predicate if there is a sequence of binary tuples ``(a0, a1)``, ``(a1, a2)``, ..., ``(an-1, an)`` that all satisfy the predicate. An ordered tuple ``(a, b)`` satisfies the ``*`` closure of a predicate if it either satisfies the ``+`` closure, or if ``a`` and ``b`` are the same, and if moreover they are in each argument type of the predicate. + +Lexical syntax +-------------- + +QL and QLL files contain a sequence of *tokens* that are encoded as Unicode text. This section describes the tokenization algorithm, the kinds of available tokens, and their representation in Unicode. + +Some kinds of tokens have an identifier given in parentheses in the section title. That identifier, if present, is a terminal used in grammar productions later in the specification. Additionally, the `Identifiers <#identifiers>`__ section gives several kinds of identifiers, each of which has its own grammar terminal. + +Tokenization +~~~~~~~~~~~~ + +Source files are interpreted as a sequence of tokens according to the following algorithm. First, the longest-match rule, described below, is applied starting at the beginning of the file. Second, all whitespace tokens and comments are discarded from the sequence. + +The longest-match rule is applied as follows. The first token in the file is the longest token consisting of a contiguous sequence of characters at the beginning of the file. The next token after any other token is the longest token consisting of contiguous characters that immediately follow any previous token. + +If the file cannot be tokenized in its entirety, then the file is invalid. + +Whitespace +~~~~~~~~~~ + +A whitespace token is a sequence of spaces (U+0020), tabs (U+0009), carriage returns (U+000D), and line feeds (U+000A). + +Comments +~~~~~~~~ + +There are two kinds of comments in QL: one-line and multiline. + +A one-line comment is two slash characters (``/``, U+002F) followed by any sequence of characters other than line feeds (U+000A) and carriage returns (U+000D). Here is an example of a one-line comment: + +:: + + // This is a comment + +A multiline comment is a *comment start*, followed by a *comment body*, followed by a *comment end*. A comment start is a slash (``/``, U+002F) followed by an asterisk (``*``, U+002A), and a comment end is an asterisk followed by a slash. A comment body is any sequence of characters that does not include a comment end. Here is an example multiline comment: + +:: + + /* + It was the best of code. + It was the worst of code. + It had a multiline comment. + */ + +Keywords +~~~~~~~~ + +The following sequences of characters are keyword tokens: + +:: + + and + any + as + asc + avg + boolean + by + class + concat + count + date + desc + else + exists + extends + false + float + forall + forex + from + if + implies + import + in + instanceof + int + max + min + module + none + not + or + order + predicate + rank + result + select + strictconcat + strictcount + strictsum + string + sum + super + then + this + true + where + +Operators +~~~~~~~~~ + +The following sequences of characters are operator tokens: + +:: + + < + <= + = + > + >= + _ + - + , + ; + != + / + . + .. + ( + ) + [ + ] + { + } + * + % + + + | + +Identifiers +~~~~~~~~~~~ + +An identifier is an optional "@" sign (U+0040) followed by a sequence of identifier characters. Identifier characters are lower-case ASCII letters (``a`` through ``z``, U+0061 through U+007A), upper-case ASCII letters (``A`` through ``Z``, U+0041 through U+005A), decimal digits (``0`` through ``9``, U+0030 through U+0039), and underscores (``_``, U+005F). The first character of an identifier other than any "@" sign must be a letter. + +An identifier cannot have the same sequence of characters as a keyword, nor can it be an "@" sign followed by a keyword. + +Here are some examples of identifiers: + +:: + + width + Window_width + window5000_mark_II + @expr + +There are several kinds of identifiers: + +- ``lowerId``: an identifier that starts with a lower-case letter. + +- ``upperId``: an identifier that starts with an upper-case letter. + +- ``atLowerId``: an identifier that starts with an "@" sign and then a lower-case letter. + +- ``atUpperId``: an identifier that starts with an "@" sign and then an upper-case letter. + +Identifiers are used in following syntactic constructs: + +:: + + simpleId ::= lowerId | upperId + modulename ::= simpleId + classname ::= upperId + dbasetype ::= atLowerId + predicateRef ::= (moduleId "::")? literalId + predicateName ::= lowerId + varname ::= simpleId + literalId ::= lowerId | atLowerId + +Integer literals (int) +~~~~~~~~~~~~~~~~~~~~~~ + +An integer literal is a possibly negated sequence of decimal digits (``0`` through ``9``, U+0030 through U+0039). Here are some examples of integer literals: + +:: + + 0 + 42 + 123 + -2147483648 + +Float literals (float) +~~~~~~~~~~~~~~~~~~~~~~ + +A floating-point literals is a possibly negated two non-negative integers literals separated by a dot (``.``, U+002E). Here are some examples of float literals: + +:: + + 0.5 + 2.0 + 123.456 + -100.5 + +String literals (string) +~~~~~~~~~~~~~~~~~~~~~~~~ + +A string literal denotes a sequence of characters. It begins and ends with a double quote character (U+0022). In between the double quotes are a sequence of string character indicators, each of which indicates one character that should be included in the string. The string character indicators are as follows. + +- Any character other than a double quote (U+0022), backslash (U+005C), line feed (U+000A), carriage return (U+000D), or tab (U+0009). Such a character indicates itself. + +- A backslash (U+005C) followed by one of the following characters: + + - Another backslash (U+005C), in which case a backslash character is indicated. + - A double quote (U+0022), in which case a double quote is indicated. + - The letter "n" (U+006E), in which case a line feed (U+000A) is indicated. + - The letter "r" (U+0072), in which case a carriage return (U+000D) is indicated. + - The letter "t" (U+0074), in which case a tab (U+0009) is indicated. + +Here are some examples of string literals: + +:: + + "hello" + "He said, \"Logic clearly dictates that the needs of the many...\"" + +Annotations +----------- + +Various kinds of syntax can have *annotations* applied to them. Annotations are as follows: + +:: + + annotations ::= annotation* + + annotation ::= simpleAnnotation | argsAnnotation + + simpleAnnotation ::= "abstract" + | "cached" + | "external" + | "final" + | "transient" + | "library" + | "private" + | "deprecated" + | "override" + | "query" + + argsAnnotation ::= "pragma" "[" ("inline" | "noinline" | "nomagic" | "noopt") "]" + | "language" "[" "monotonicAggregates" "]" + | "bindingset" "[" (variable ( "," variable)*)? "]" + +Each simple annotation adds a same-named attribute to the syntactic entity it precedes. For example, if a class is preceded by the ``abstract`` annotation, then the class is said to be abstract. + +A valid annotation list may not include the same simple annotation more than once, or the same parameterized annotation more than once with the same arguments. However, it may include the same parameterized annotation more than once with different arguments. + +Simple annotations +~~~~~~~~~~~~~~~~~~ + +The following table summarizes the syntactic constructs which can be marked with each annotation in a valid program; for example, an ``abstract`` annotation preceding a character is invalid. + ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| Annotation | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | ++================+=========+============+===================+=======================+=========+========+=========+=========+ +| ``abstract`` | yes | | yes | | | | | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``cached`` | yes | yes | yes | yes | | | yes | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``external`` | | | | yes | | | | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``final`` | yes | | yes | | | yes | | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``transient`` | | | | yes | | | | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``library`` | yes | | | | | | | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``private`` | yes | | yes | yes | yes | yes | yes | yes | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``deprecated`` | yes | | yes | yes | | yes | yes | yes | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``override`` | | | yes | | | yes | | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``query`` | | | | yes | | | | yes | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ + +The ``library`` annotation is only usable within a QLL file, not a QL file. + +Annotations on aliases apply to the name introduced by the alias. An alias may, for example, have different privacy to the name it aliases. + +Parameterized annotations +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Parameterized annotations take some additional arguments. + +The parameterized annotation ``pragma`` supplies compiler pragmas, and may be applied in various contexts depending on the pragma in question. + ++--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| Pragma | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | ++==============+=========+============+===================+=======================+=========+========+=========+=========+ +| ``inline`` | | yes | yes | yes | | | | | ++--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``noinline`` | | yes | yes | yes | | | | | ++--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``nomagic`` | | yes | yes | yes | | | | | ++--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| ``noopt`` | | yes | yes | yes | | | | | ++--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ + +The parameterized annotation ``language`` supplies language pragmas which change the behavior of the language. Language pragmas apply at the scope level, and are inherited by nested scopes. + ++-------------------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| Pragma | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | ++=========================+=========+============+===================+=======================+=========+========+=========+=========+ +| ``monotonicAggregates`` | yes | yes | yes | yes | | | yes | | ++-------------------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ + +A binding set for a predicate is a subset of the predicate’s arguments such that if those arguments are bound (restricted to a finite range of values), then all of the predicate’s arguments are bound. + +The parameterized annotation ``bindingset`` can be applied to a predicate (see `Non-member predicates <#non-member-predicates>`__ and `Members <#members>`__) to specify a binding set. + +This annotation accepts a (possibly empty) list of variable names as parameters. The named variables must all be arguments of the predicate, possibly including ``this`` for characteristic predicates and member predicates, and ``result`` for predicates that yield a result. + +In the default case where no binding sets are specified by the user, then it is assumed that there is precisely one, empty binding set - that is, the body of the predicate must bind all the arguments. + +Binding sets are checked by the QL compiler in the following way: + +#. It assumes that all variables mentioned in the binding set are bound. +#. It checks that, under this assumption, all the remaining argument variables are bound by the predicate body. + +A predicate may have several different binding sets, which can be stated by using multiple ``bindingset`` annotations on the same predicate. + ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +| Pragma | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | ++================+=========+============+===================+=======================+=========+========+=========+=========+ +| ``bindingset`` | | yes | yes | yes | | | | | ++----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ + +Top-level entities +------------------ + +Modules include five kinds of top-level entity: predicates, classes, modules, aliases, and select clauses. + +Non-member predicates +~~~~~~~~~~~~~~~~~~~~~ + +A *predicate* is declared as a sequence of annotations, a head, and an optional body: + +:: + + predicate ::= annotations head optbody + +A predicate definition adds a mapping from the predicate name and arity to the predicate declaration to the current module's declared predicate environment. + +When a predicate is a top-level clause in a module, it is called a non-member predicate. See below for `member predicates <#member-predicates>`__. + +A valid non-member predicate can be annotated with ``cached``, ``deprecated``, ``external``, ``transient``, ``private``, and ``query``. Note, the ``transient`` annotation can only be applied if the non-member predicate is also annotated with ``external``. + +The head of the predicate gives a name, an optional *result type*, and a sequence of variables declarations that are *arguments*: + +:: + + head ::= ("predicate" | type) predicateName "(" (var_decls)? ")" + +The body of a predicate is of one of three forms: + +:: + + optbody ::= ";" + | "{" formula "}" + | "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")" + +In the first form, with just a semicolon, the predicate is said to not have a body. In the second form, the body of the predicate is the given formula (see `Formulas <#formulas>`__). In the third form, the body is a higher-order relation. + +A valid non-member predicate must have a body, either a formula or a higher-order relation, unless it is external, in which case it must not have a body. + +The typing environment for the body of the formula, if present, maps the variables in the head of the predicate to their associated types. If the predicate has a result type, then the typing environment also maps ``result`` to the result type. + +Classes +~~~~~~~ + +A class definition has the following syntax: + +:: + + class ::= annotations "class" classname "extends" type ("," type)* "{" member* "}" + +The identifier following the ``class`` keyword is the name of the class. + +The types specified after the ``extends`` keyword are the *base types* of the class. + +A class domain type is said to *inherit* from the base types of the associated class type, a character type is said to *inherit* from its associated class domain type and a class type is said to *inherit* from its associated character type. In addition, inheritance is transitive: If a type ``A`` inherits from a type ``B``, and ``B`` inherits from a type ``C``, then ``A`` inherits from ``C``. + +A class adds a mapping from the class name to the class declaration to the current module's declared type environment. + +A valid class can be annotated with ``abstract``, ``final``, ``library``, and ``private``. Any other annotation renders the class invalid. + +A valid class may not inherit from a final class, from itself, or from more than one primitive type. + +Class environments +~~~~~~~~~~~~~~~~~~ + +For each of modules, types, predicates, and fields a class *inherits*, *declares*, and *exports* an environment. These are defined as follows (with X denoting the type of entity we are currently considering): + +- The *inherited X environment* of a class is the union of the exported X environments of its base types. + +- The *declared X environment* of a class is the multimap of X declarations in the class itself. + +- The *exported X environment* of a class is the overriding union of its declared X environment (excluding ``private`` declaration entries) with its inherited X environment. + +- The *external X environment* of a class is the visible X environment of the enclosing module. + +- The *visible X environment* is the overriding union of the declared X environment and the inherited X environment; overriding unioned with the external X environment. + +The program is invalid if any of these environments is not definite. + +Members +~~~~~~~ + +Each member of a class is either a *character*, a predicate, or a field: + +:: + + member ::= character | predicate | field + character ::= annotations classname "(" ")" "{" formula "}" + field ::= annotations var_decl ";" + +Characters +^^^^^^^^^^ + +A valid character must have the same name as the name of the class. A valid class has at most one character provided in the source code. + +A valid character can be annotated with ``cached``. Any other annotation renders the character invalid. + +Member predicates +^^^^^^^^^^^^^^^^^ + +A predicate that is a member of a class is called a *member predicate*. The name of the predicate is the identifier just before the open parenthesis. + +A member predicate adds a mapping from the predicate name and arity to the predicate declaration in the class's declared predicate environment. + +A valid member predicate can be annotated with ``abstract``, ``cached``, ``final``, ``private``, ``deprecated``, and ``override``. + +If a type is provided before the name of the member predicate, then that type is the *result type* of the predicate. Otherwise, the predicate has no result type. The types of the variables in the ``var_decls`` are called the predicate's *argument types*. + +A member predicate ``p`` with enclosing class ``C`` *overrides* a member predicate ``p'`` with enclosing class ``D`` when ``C`` inherits from ``D``, ``p'`` is visible in ``C``, and both ``p`` and ``p'`` have the same name and the same arity. An overriding predicate must have the same sequence of argument types as any predicates which it overrides, otherwise the program is invalid. + +Member predicates have one or more *root definitions*. If a member predicate overrides no other member predicate, then it is its own root definition. Otherwise, its root definitions are those of any member predicate that it overrides. + +A valid member predicate must have a body unless it is abstract or external, in which case it must not have a body. + +A valid member predicate must override another member predicate if it is annotated override. + +When member predicate ``p`` overrides member predicate ``q``, either ``p`` and ``q`` must both have a result type, or neither of them may have a result type. If they do have result types, then the result type of ``p`` must be a subtype of the result type of ``q``. ``q`` may not be a final predicate. If ``p`` is abstract, then ``q`` must be as well. + +A class may not inherit from a class with an abstract member predicate unless it either includes a member predicate overriding that abstract predicate, or it inherits from another class that does. + +A valid class must include a non-private predicate named ``toString`` with no arguments and a result type of ``string``, or it must inherit from a class that does. + +A valid class may not inherit from two different classes that include a predicate with the same name and number of arguments, unless either one of the predicates overrides the other, or the class defines a predicate that overrides both of them. + +The typing environment for a member predicate or character is the same as if it were a non-member predicate, except that it additionally maps ``this`` to a type. If the member is a character, then the typing environment maps ``this`` to the class domain type of the class. Otherwise, it maps ``this`` to the class type of the class itself. + +Fields +^^^^^^ + +A field declaration introduces a mapping from the field name to the field declaration in the class's declared field environment. + +Select clauses +~~~~~~~~~~~~~~ + +A QL file may include at most one *select clause*. That select clause has the following syntax: + +:: + + select ::= ("from" var_decls)? ("where" formula)? "select" select_exprs ("order" "by" orderbys)? + +A valid QLL file may not include any select clauses. + +A select clause is considered to be a declaration of an anonymous predicate whose arguments correspond to the select expressions of the select clause. + +The ``from`` keyword, if present, is followed by the *variables* of the formula. Otherwise, the select clause has no variables. + +The ``where`` keyword, if present, is followed by the *formula* of the select clause. Otherwise, the select clause has no formula. + +The ``select`` keyword is followed by a number of *select expressions*. Select expressions have the following syntax: + +:: + + as_exprs ::= as_expr ("," as_expr)* + as_expr ::= expr ("as" simpleId)? + +The keyword ``as`` gives a *label* to the select expression it is part of. No two select expressions may have the same label. No expression label may be the same as one of the variables of the select clause. + +The ``order`` keyword, if present, is followed by a number of *ordering directives*. Ordering directives have the following syntax: + +:: + + orderbys ::= orderby ("," orderby)* + orderby ::= simpleId ("asc" | "desc")? + +Each identifier in an ordering directive must identify exactly one of the select expressions. It must either be the label of the expression, or it must be a variable expression that is equivalent to exactly one of the select expressions. The type of the designated select expression must be a subtype of a primitive type. + +No select expression may be specified by more than one ordering directive. See `Ordering <#ordering>`__ for more information. + +Queries +~~~~~~~ + +The queries in a QL module are: + +- The select clause, if any, defined in that module. +- Any predicates annotated with ``query`` which are in scope in that module. + +The target predicate of the query is either the select clause or the annotated predicate. + +Each argument of the target predicate of the query must be of a type which has a ``toString()`` member predicate. + +Expressions +----------- + +Expressions are a form of syntax used to denote values. Every expression has a typing environment that is determined by the context where the expression occurs. Every valid expression has a type, as specified in this section, except if it is a don't-care expression. + +Given a named tuple and a store, each expression has one or more *values*. This section specifies the values of each kind of expression. + +There are several kinds of expressions: + +:: + + exprs ::= expr ("," expr)* + + expr ::= dontcare + | unop + | binop + | cast + | primary + + primary ::= eparen + | literal + | variable + | super_expr + | callwithresult + | postfix_cast + | aggregation + | any + +Parenthesized expressions +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A parenthesized expression is an expression surrounded by parentheses: + +:: + + eparen ::= "(" expr ")" + +The type environment of the nested expression is the same as that of the outer expression. The type and values of the outer expression are the same as those of the nested expression. + +Don't-care expressions +~~~~~~~~~~~~~~~~~~~~~~ + +A don't-care expression is written as a single underscore: + +:: + + dontcare ::= "_" + +All values are values of a don't-care expression. + +Literals +~~~~~~~~ + +A literal expression is as follows: + +:: + + literal ::= "false" | "true" | int | float | string + +The type of a literal expression is the type of the value denoted by the literal: ``boolean`` for ``false`` or ``true``, ``int`` for an integer literal, ``float`` for a floating-point literal, or ``string`` for a string literal. The value of a literal expression is the same as the value denoted by the literal. + +Unary operations +~~~~~~~~~~~~~~~~ + +A unary operation is the application of ``+`` or ``-`` to another expression: + +:: + + unop ::= "+" expr + | "-" expr + +The ``+`` or ``-`` in the operation is called the *operator*, and the expression is called the *operand*. The typing environment of the operand is the same as for the unary operation. + +For a valid unary operation, the operand must be of type ``int`` or ``float``. The operation has the same type as its operand. + +If the operator is ``+``, then the values of the expression are the same as the values of the operand. If the operator is ``-``, then the values of the expression are the arithmetic negations of the values of the operand. + +Binary operations +~~~~~~~~~~~~~~~~~ + +A binary operation is written as a *left operand* followed by a *binary operator*, followed by a *right operand*: + +:: + + binop ::= expr "+" expr + | expr "-" expr + | expr "*" expr + | expr "/" expr + | expr "%" expr + +The typing environment for the two environments is the same as for the operation. If the operator is ``+``, then either both operands must be subtypes of ``int`` or ``float``, or at least one operand must be a subtype of ``string``. If the operator is anything else, then each operand must be a subtype of ``int`` or ``float``. + +The type of the operation is ``string`` if either operand is a subtype of ``string``. Otherwise, the type of the operation is ``int`` if both operands are subtypes of ``int``. Otherwise, the type of the operation is ``float``. + +If the result is of type ``string``, then the *left values* of the operation are the values of a "call with results" expression with the left operand as the receiver, ``toString`` as the predicate name, and no arguments (see `Calls with results <#calls-with-results>`__). Otherwise the left values are the values of the left operand. Likewise, the *right values* are either the values from calling ``toString`` on the right operand, or the values of the right operand as it is. + +The binary operation has one value for each combination of a left value and a right value. That value is determined as follows: + +- If the left and right operand types are subtypes of string, then the operation has a value that is the concatenation of the left and right values. + +- Otherwise, if both operand types are subtypes of ``int``, then the value of the operation is the result of applying the two's-complement 32-bit integer operation corresponding to the QL binary operator. + +- Otherwise, both operand types must be subtypes of ``float``. If either operand is of type ``int`` then they are converted to a float. The value of the operation is then the result of applying the IEEE 754 floating-point operator that corresponds to the QL binary operator: addition for ``+``, subtraction for ``-``, multiplication for ``*``, division for ``/``, or remainder for ``%``. + +Variables +~~~~~~~~~ + +A variable has the following syntax: + +:: + + variable ::= varname | "this" | "result" + +A valid variable expression must occur in the typing environment. The type of the variable expression is the same as the type of the variable in the typing environment. + +The value of the variable is the value of the variable in the named tuple. + +Super +~~~~~ + +A super expression has the following syntax: + +:: + + super_expr ::= "super" | type "." "super" + +For a super expression to be valid, the ``this`` keyword must have a type and value in the typing environment. The type of the expression is the same as the type of ``this`` in the typing environment. + +A super expression may only occur in a QL program as the receiver expression for a predicate call. + +If a super expression includes a ``type``, then that type must be a class that the enclosing class inherits from. + +If the super expression does not include a type, then the enclosing class must have a single declared base type, and that base type must be a class. + +The value of a super expression is the same as the value of ``this`` in the named tuple. + +Casts +~~~~~ + +A cast expression is a type in parentheses followed by another expression: + +:: + + cast ::= "(" type ")" expr + +The typing environment for the nested expression is the same as for the cast expression. The type of the cast expression is the type between parentheses. + +The values of the cast expression are those values of the nested expression that are in the type given within parentheses. + +For casts between the primitive ``float`` and ``int`` types, the above rule means that for the cast expression to have a value, it must be representable as both 32-bit two's complement integers and 64-bit IEEE 754 floats. Other values will not be included in the values of the cast expression. + +Postfix casts +~~~~~~~~~~~~~ + +*Available from Semmle 1.9.4 onward.* A postfix cast is a primary expression followed by a dot and then a class or primitive type in parentheses: + +:: + + postfix_cast ::= primary "." "(" type ")" + +All the rules for ordinary casts apply to postfix casts: a postfix cast is exactly equivalent to a parenthesized ordinary cast. + +Calls with results +~~~~~~~~~~~~~~~~~~ + +An expression for a call with results is of one of two forms: + +:: + + callwithresult ::= predicateRef (closure)? "(" (exprs)? ")" + | primary "." predicateName (closure)? "(" (exprs)? ")" + closure ::= "*" | "+" + +The expressions in parentheses are the *arguments* of the call. The expression before the dot, if there is one, is the *receiver* of the call. + +The type environment for the arguments is the same as for the call. + +A valid call with results must *resolve* to exactly one predicate. The ways a call can resolve are as follows: + +- If the call has no receiver, then it can resolve to a non-member predicate. If the predicate name is a simple identifier, then the predicate is resolved by looking up its name and arity in the visible predicate environment of the enclosing class or module. + + If the predicate name is a selection identifier, then the qualifier is resolved as a module (see `Module resolution <#module-resolution>`__). The identifier is then resolved in the exported predicate environment of the qualifier module. + +- If the call has a super expression as the receiver, then it resolves to a member predicate in a class the enclosing class inherits from. If the super expression is unqualified, then the super-class is the single class that the current class inherits from. If there is not exactly one such class, then the program is invalid. Otherwise the super-class is the class named by the qualifier of the super expression. The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. If there is more than one such predicate, then the predicate call is not valid. + +For each argument other than a don't-care expression, the type of the argument must be compatible with the type of the corresponding argument type of the predicate, otherwise the call is invalid. + +A valid call with results must resolve to a predicate that has a result type. That result type is also the type of the call. + +If the resolved predicate is built in, then the call may not include a closure. If the call does have a closure, then it must resolve to a predicate where the *relational arity* of the predicate is 2. The relational arity of a predicate is the sum of the following numbers: + +- The number of arguments to the predicate. + +- The number 1 if the predicate is a member predicate, otherwise 0. + +- The number 1 if the predicate has a result, otherwise 0. + +If the call resolves to a member predicate, then the *receiver values* are as follows. If the call has a receiver, then the receiver values are the values of that receiver. If the call does not have a receiver, then the single receiver value is the value of ``this`` in the contextual named tuple. + +The *tuple prefixes* of a call with results include one value from each of the argument expressions' values, in the same order as the order of the arguments. If the call resolves to a non-member predicate, then those values are exactly the tuple prefixes of the call. If the call instead resolves to a member predicate, then the tuple prefixes additionally include a receiver value, ordered before the argument values. + +The *matching tuples* of a call with results are all ordered tuples that are one of the tuple prefixes followed by any value of the same type as the call. If the call has no closure, then all matching tuples must additionally satisfy the resolved predicate of the call, unless the receiver is a super expression, in which case they must *directly* satisfy the resolved predicate of the call. If the call has a ``*`` or ``+`` closure, then the matching tuples must satisfy or directly satisfy the associated closure of the resolved predicate. + +The values of a call with results are the final elements of each of the call's matching tuples. + +Aggregations +~~~~~~~~~~~~ + +An aggregation can be written in one of two forms: + +:: + + aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" + | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" + | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" + + aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" + + aggorderbys ::= aggorderby ("," aggorderby)* + + aggorderby ::= expr ("asc" | "desc")? + +The expression enclosed in square brackets (``[`` and ``]``, U+005B and U+005D), if present, is called the *rank expression*. It must have type ``int`` in the enclosing environment. + +The ``as_exprs``, if present, are called the *aggregation expressions*. If an aggregation expression is of the form ``expr as v`` then the expression is said to be *named* v. + +The rank expression must be present if the aggregate id is ``rank``; otherwise it must not be present. + +Apart from the presence or absence of the rank variable, all other reduced forms of an aggregation are equivalent to a full form using the following steps: + +- If the formula is omitted, then it is taken to be ``any()``. +- If there are no aggregation expressions, then either: + + - The aggregation id is ``count`` or ``strictcount`` and the expression is taken to be ``1``. + - There must be precisely one variable declaration, and the aggregation expression is taken to be a reference to that variable. + +- If the aggregation id is ``concat`` or ``strictconcat`` and it has a single expression then the second expression is taken to be ``""``. +- If the ``monotonicAggregates`` language pragma is not enabled, or the original formula and variable declarations are both omitted, then the aggregate is transformed as follows: + + - For each aggregation expression ``expr_i``, a fresh variable ``v_i`` is declared with the same type as the expression in addition to the original variable declarations. + - The new range is the conjunction of the original range and a term ``v_i = expr_i`` for each aggregation expression ``expr_i``. + - Each original aggregation expression ``expr_i`` is replaced by a new aggregation expression ``v_i``. + +The variables in the variable declarations list must not occur in the typing environment. + +The typing environment for the rank expression is the same as for the aggregation. + +The typing environment for the formula is obtained by taking the typing environment for the aggregation and adding all the variable types in the given ``var_decls`` list. + +The typing environment for an aggregation expression is obtained by taking the typing environment for the formula and then, for each named aggregation expression that occurs earlier than the current expression, adding a mapping from the earlier expression's name to the earlier expression's type. + +The typing environment for ordering directives is obtained by taking the typing environment for the formula and then, for each named aggregation expression in the aggregation, adding a mapping from the expression's name to the expression's type. + +The number and types of the aggregation expressions are restricted as follows: + +- A ``max``, ``min``, ``rank`` or ``unique`` aggregation must have a single expression. +- The type of the expression in a ``max``, ``min`` or ``rank`` aggregation without an ordering directive expression must be an orderable type. +- A ``count`` or ``strictcount`` aggregation must not have an expression. +- A ``sum``, ``strictsum`` or ``avg`` aggregation must have a single aggregation expression, which must have a type which is a subtype of ``float``. +- A ``concat`` or ``strictconcat`` aggregation must have two expressions. Both expressions must have types which are subtypes of ``string``. + +The type of a ``count``, ``strictcount`` aggregation is ``int``. The type of an ``avg`` aggregation is ``float``. The type of a ``concat`` or ``strictconcat`` aggregation is ``string``. The type of a ``sum`` or ``strictsum`` aggregation is ``int`` if the aggregation expression is a subtype of ``int``, otherwise it is ``float``. The type of a ``rank``, ``min`` or ``max`` aggregation is the type of the single expression. + +An ordering directive may only be specified for a ``max``, ``min``, ``rank``, ``concat`` or ``strictconcat`` aggregation. The type of the expression in an ordering directive must be an orderable type. + +The values of the aggregation expression are determined as follows. Firstly, the *range tuples* are extensions of the named tuple that the aggregation is being evaluated in with the variable declarations of the aggregation, and which *match* the formula (see `Formulas <#formulas>`__). + +For each range tuple, the *aggregation tuples* are the extension of the range tuples to *aggregation variables* and *sort variables*. + +The aggregation variables are given by the aggregation expressions. If an aggregation expression is named, then its aggregation variable is given by its name, otherwise a fresh synthetic variable is created. The value is given by evaluating the expression with the named tuple being the result of the previous expression, or the range tuple if this is the first aggregation expression. + +The sort variables are synthetic variables created for each expression in the ordering directive with values given by the values of the expressions within the ordering directive. + +If the aggregation id is ``max``, ``min`` or ``rank`` and there was no ordering directive, then for each aggregation tuple a synthetic sort variable is added with value given by the aggregation variable. + +The values of the aggregation expression are given by applying the aggregation function to each set of tuples obtained by picking exactly one aggregation tuple for each range tuple. + +- If the aggregation id is ``avg``, and the set is non-empty, then the resulting value is the average of the value for the aggregation variable in each tuple in the set, weighted by the number of tuples in the set, after converting the value to a floating-point number. + +- If the aggregation id is ``count``, then the resulting value is the number of tuples in the set. If there are no tuples in the set, then the value is the integer ``0``. + +- If the aggregation id is ``max``, then the values are the those values of the aggregation variable which are associated with a maximal tuple of sort values. If the set is empty, then the aggregation has no value. + +- If the aggregation id is ``min``, then the values are the those values of the aggregation variable which are associated with a minimal tuple of sort values. If the set is empty, then the aggregation has no value. + +- If the aggregation id is ``rank``, then the resulting values are values of the aggregation variable such that the number of aggregation tuples with a strictly smaller tuple of sort variables is exactly one less than an integer bound by the rank expression of the aggregation. If no such values exist, then the aggregation has no values. + +- If the aggregation id is ``strictcount``, then the resulting value is the same as if the aggregation id were ``count``, unless the set of tuples is empty. If the set of tuples is empty, then the aggregation has no value. + +- If the aggregation id is ``strictsum``, then the resulting value is the same as if the aggregation id were ``sum``, unless the set of tuples is empty. If the set of tuples is empty, then the aggregation has no value. + +- If the aggregation id is ``sum``, then the resulting value is the same as the sum of the values of the aggregation variable across the tuples in the set, weighted by the number of times each value occurs in the tuples in the set. If there are no tuples in the set, then the resulting value of the aggregation is the integer ``0``. + +- If the aggregation id is ``concat``, then there is one value for each value of the second aggregation variable, given by the concatenation of the value of the first aggregation variable of each tuple with the value of the second aggregation variable used as a separator, ordered by the sort variables. If there are multiple aggregation tuples with the same sort variables then the first distinguished value is used to break ties. If there are no tuples in the set, then the single value of the aggregation is the empty string. + +- If the aggregation id is ``strictconcat``, then the result is the same as for ``concat`` except in the case where there are no aggregation tuples in which case the aggregation has no value. + + - If the aggregation id is ``unique``, then the result is the value of the aggregation variable if there is precisely one such value. Otherwise, the aggregation has no value. + +Any +~~~ + +The ``any`` expression is a special kind of quantified expression. + +:: + + any ::= "any" "(" var_decls ("|" (formula)? ("|" expr)?)? ")" + +The values of an ``any`` expression are those values of the expression for which the formula matches. + +The abbreviated cases for an ``any`` expression are interpreted in the same way as for an aggregation. + +Ranges +~~~~~~ + +Range expressions denote a range of values. + +:: + + range ::= "[" expr ".." expr "]" + +Both expressions must be subtypes of ``int``, ``float``, or ``date``. If either of them are type ``date``, then both of them must be. + +If both expressions are subtypes of ``int`` then the type of the range is ``int``. If both expressions are subtypes of ``date`` then the type of the range is ``date``. Otherwise the type of the range is ``float``. + +The values of a range expression are those values which are ordered inclusively between a value of the first expression and a value of the second expression. + +Set literals +~~~~~~~~~~~~ + +Set literals denote a choice from a collection of values. + +:: + + setliteral ::= "[" expr ("," expr)* "]" + +Set literals can be of any type, but the types within a set literal have to be consistent according to the following criterion: At least one of the set elements has to be of a type that is a supertype of all the set element types. This supertype is the type of the set literal. For example, ``float`` is a supertype of ``float`` and ``int``, therefore ``x = [4, 5.6]`` is valid. On the other hand, ``y = [5, "test"]`` does not adhere to the criterion. + +The values of a set literal expression are all the values of all the contained element expressions. + +Set literals are supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise. + +Disambiguation of expressions +----------------------------- + +The grammar given in this section is disambiguated first by precedence, and second by associating left to right. The order of precedence from highest to lowest is: + +- casts +- unary ``+`` and ``-`` +- binary ``*`` , ``/`` and ``%`` +- binary ``+`` and ``-`` + +Additionally, whenever a sequence of tokens can be interpreted either as a call to a predicate with result (with specified closure), or as a binary operation with operator ``+`` or ``*``, the syntax is interpreted as a call to a predicate with result. + +Formulas +-------- + +A formula is a form of syntax used to *match* a named tuple given a store. + +There are several kinds of formulas: + +:: + + formula ::= fparen + | disjunction + | conjunction + | implies + | ifthen + | negated + | quantified + | comparison + | instanceof + | inrange + | call + +This section specifies the syntax for each kind of formula and what tuples they match. + +Parenthesized formulas +~~~~~~~~~~~~~~~~~~~~~~ + +A parenthesized formula is a formula enclosed by a pair of parentheses: + +:: + + fparen ::= "(" formula ")" + +A parenthesized formula matches the same tuples as the nested formula matches. + +Disjunctions +~~~~~~~~~~~~ + +A disjunction is two formulas separated by the ``or`` keyword: + +:: + + disjunction ::= formula "or" formula + +A disjunction matches any tuple that matches either of the nested formulas. + +Conjunctions +~~~~~~~~~~~~ + +A conjunction is two formulas separated by the ``and`` keyword: + +:: + + conjunction ::= formula "and" formula + +A conjunction matches any tuple that also matches both of the two nested formulas. + +Implications +~~~~~~~~~~~~ + +An implication formula is two formulas separated by the ``implies`` keyword: + +:: + + implies ::= formula "implies" formula + +Neither of the two formulas may be another implication. + +An implied formula matches if either the second formula matches, or the first formula does not match. + +Conditional formulas +~~~~~~~~~~~~~~~~~~~~ + +A conditional formula has the following syntax: + +:: + + ifthen ::= "if" formula "then" formula "else" formula + +The first formula is called the *condition* of the conditional formula. The second formula is called the *true branch*, and the second formula is called the *false branch*. + +The conditional formula matches if the condition and the true branch both match. It also matches if the false branch matches and the condition does not match. + +Negations +~~~~~~~~~ + +A negation formula is a formula preceded by the ``not`` keyword: + +:: + + negated ::= "not" formula + +A negation formula matches any tuple that does not match the nested formula. + +Quantified formulas +~~~~~~~~~~~~~~~~~~~ + +A quantified formula has several syntaxes: + +:: + + quantified ::= "exists" "(" expr ")" + | "exists" "(" var_decls ("|" formula)? ("|" formula)? ")" + | "forall" "(" var_decls ("|" formula)? "|" formula ")" + | "forex" "(" var_decls ("|" formula)? "|" formula ")" + +In all cases, the typing environment for the nested expressions or formulas is the same as the typing environment for the quantified formula, except that it also maps the variables in the variable declaration to their associated types. + +The first form matches if the given expression has at least one value. + +For the other forms, the extensions of the current named tuple for the given variable declarations are called the *quantifier extensions*. The nested formulas are called the *first quantified formula* and, if present, the *second quantified formula*. + +The second ``exists`` formula matches if one of the quantifier extensions is such that the quantified formula or formulas all match. + +A ``forall`` formula that has one quantified formula matches if that quantified formula matches all of the quantifier extensions. A ``forall`` with two quantified formulas matches if the second formula matches all extensions where the first formula matches. + +A ``forex`` formula with one quantified formula matches under the same conditions as a ``forall`` formula matching, except that there must be at least one quantifier extension where that first quantified formula matches. + +Comparisons +~~~~~~~~~~~ + +A comparison formula is two expressions separated by a comparison operator: + +:: + + comparison ::= expr compop expr + compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" + +A comparison formula matches if there is one value of the left expression that is in the given ordering with one of the values of the right expression. The ordering used is specified in `Ordering <#ordering>`__. If one of the values is an integer and the other is a float value, then the integer is converted to a float value before the comparison. + +If the operator is ``=``, then at least one of the left and right expressions must have a type; if they both have a type, those types must be compatible. + +If the operator is ``!=``, then both expressions must have a type, and those types must be compatible. + +If the operator is any other operator, then both expressions must have a type. Those types must be compatible with each other. Each of those types must be orderable. + +Type checks +~~~~~~~~~~~ + +A type check formula has the following syntax: + +:: + + instanceof ::= expr "instanceof" type + +The type to the right of ``instanceof`` is called the *type-check type*. + +The type of the expression must be compatible with the type-check type. + +The formula matches if one of the values of the expression is in the type-check type. + +Range checks +~~~~~~~~~~~~ + +A range check has the following syntax: + +:: + + inrange ::= expr "in" range + +The formula is equivalent to ``expr "=" range``. + +Calls +~~~~~ + +A call has the following syntax: + +:: + + call ::= predicateRef (closure)? "(" (exprs)? ")" + | primary "." predicateName (closure)? "(" (exprs)? ")" + +The identifier is called the *predicate name* of the call. + +A call must resolve to a predicate, using the same definition of resolve as for calls with results (see `Calls with results <#calls-with-results>`__). + +The resolved predicate must not have a result type. + +If the resolved predicate is a built-in member predicate of a primitive type, then the call may not include a closure. If the call does have a closure, then the call must resolve to a predicate with relational arity of 2. + +The *candidate tuples* of a call are the ordered tuples formed by selecting a value from each of the arguments of the call. + +If the call has no closure, then it matches whenever one of the candidate tuples satisfies the resolved predicate of the call, unless the call has a super expression as a receiver, in which case the candidate tuple must *directly* satisfy the resolved predicate. If the call has ``*`` or ``+`` closure, then the call matches whenever one of the candidate tuples satisfies or directly satisfies the associated closure of the resolved predicate. + +Disambiguation of formulas +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The grammar given in this section is disambiguated first by precedence, and second by associating left to right, except for implication which is non-associative. The order of precedence from highest to lowest is: + +- Negation + +- Conditional formulas + +- Conjunction + +- Disjunction + +- Implication + +Aliases +------- + +Aliases define new names for existing QL entities. + +:: + + alias ::= annotations "predicate" literalId "=" predicateRef "/" int ";" + | annotations "class" classname "=" type ";" + | annotations "module" modulename "=" moduleId ";" + + +An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively. + +Built-ins +--------- + +A QL database includes a number of *built-in predicates* . This section defines a number of built-in predicates that all databases include. Each database also includes a number of additional non-member predicates that are not specified in this document. + +This section gives several tables of built-in predicates. For each predicate, the table gives the result type of each predicate that has one, and the sequence of argument types. + +Each table also specifies which ordered tuples are in the database content of each predicate. It specifies this with a description that holds true for exactly the tuples that are included. In each description, the "result" is the last element of each tuple, if the predicate has a result type. The "receiver" is the first element of each tuple. The "arguments" are all elements of each tuple other than the result and the receiver. + +Non-member built-ins +~~~~~~~~~~~~~~~~~~~~ + +The following built-in predicates are non-member predicates: + ++-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Name | Result type | Argument types | Content | ++===========+=============+====================================+============================================================================================================================================================================================================+ +| ``any`` | | | The empty tuple. | ++-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``none`` | | | No tuples. | ++-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``toUrl`` | | string, int, int, int, int, string | Let the arguments be ``file``, ``startLine``, ``startCol``, ``endLine``, ``endCol``, and ``url``. The predicate holds if ``url`` is equal to the string ``file://file:startLine:startCol:endLine:endCol``. | ++-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +Built-ins for boolean +~~~~~~~~~~~~~~~~~~~~~ + +The following built-in predicates are members of type ``boolean``: + ++----------------+-------------+----------------+--------------------------------------------------------------------------+ +| Name | Result type | Argument types | Content | ++================+=============+================+==========================================================================+ +| ``booleanAnd`` | boolean | boolean | The result is the boolean and of the receiver and the argument. | ++----------------+-------------+----------------+--------------------------------------------------------------------------+ +| ``booleanNot`` | boolean | | The result is the boolean not of the receiver. | ++----------------+-------------+----------------+--------------------------------------------------------------------------+ +| ``booleanOr`` | boolean | boolean | The result is the boolean or of the receiver and the argument. | ++----------------+-------------+----------------+--------------------------------------------------------------------------+ +| ``booleanXor`` | boolean | boolean | The result is the boolean exclusive or of the receiver and the argument. | ++----------------+-------------+----------------+--------------------------------------------------------------------------+ +| ``toString`` | string | | The result is "true" if the receiver is ``true``, otherwise "false." | ++----------------+-------------+----------------+--------------------------------------------------------------------------+ + +Built-ins for date +~~~~~~~~~~~~~~~~~~ + +The following built-in predicates are members of type ``date``: + ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| Name | Result type | Argument types | Content | ++================+=============+================+================================================================================================+ +| ``daysTo`` | int | date | The result is the number of days between but not including the receiver and the argument. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``getDay`` | int | | The result is the day component of the receiver. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``getHours`` | int | | The result is the hours component of the receiver. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``getMinutes`` | int | | The result is the minutes component of the receiver. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``getMonth`` | string | | The result is a string that is determined by the month component of the receiver. | +| | | | The string is one of ``January``, ``February``, ``March``, ``April``, ``May``, ``June``, | +| | | | ``July``, ``August``, ``September``, ``October``, ``November``, or ``December``. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``getSeconds`` | int | | The result is the seconds component of the receiver. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``getYear`` | int | | The result is the year component of the receiver. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``toISO`` | string | | The result is a string representation of the date. The representation is left unspecified. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ +| ``toString`` | string | | The result is a string representation of the date. The representation is left unspecified. | ++----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ + +Built-ins for float +~~~~~~~~~~~~~~~~~~~ + +The following built-in predicates are members of type ``float``: + ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| Name | Result type | Argument types | Content | ++===============+=============+================+===========================================================================================================================+ +| ``abs`` | float | | The result is the absolute value of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``acos`` | float | | The result is the inverse cosine of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``asin`` | float | | The result is the inverse sine of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``atan`` | float | | The result is the inverse tangent of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``ceil`` | int | | The result is the smallest integer greater than or equal to the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``copySign`` | float | float | The result is the floating point number with the magnitude of the receiver and the sign of the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``cos`` | float | | The result is the cosine of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``cosh`` | float | | The result is the hyperbolic cosine of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``exp`` | float | | The result is the value of e, the base of the natural logarithm, raised to the power of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``floor`` | int | | The result is the largest integer that is not greater than the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``log`` | float | | The result is the natural logarithm of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``log`` | float | float | The result is the logarithm of the receiver with the base of the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``log`` | float | int | The result is the logarithm of the receiver with the base of the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``log10`` | float | | The result is the base-10 logarithm of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``log2`` | float | | The result is the base-2 logarithm of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``maximum`` | float | float | The result is the larger of the receiver and the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``maximum`` | float | int | The result is the larger of the receiver and the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``minimum`` | float | float | The result is the smaller of the receiver and the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``minimum`` | float | int | The result is the smaller of the receiver and the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``nextAfter`` | float | float | The result is the number adjacent to the receiver in the direction of the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``nextDown`` | float | | The result is the number adjacent to the receiver in the direction of negative infinity. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``nextUp`` | float | | The result is the number adjacent to the receiver in the direction of positive infinity. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``pow`` | float | float | The result is the receiver raised to the power of the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``pow`` | float | int | The result is the receiver raised to the power of the argument. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``signum`` | float | | The result is the sign of the receiver: zero if it is zero, 1.0 if it is greater than zero, -1.0 if it is less than zero. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``sin`` | float | | The result is the sine of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``sinh`` | float | | The result is the hyperbolic sine of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``sqrt`` | float | | The result is the square root of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``tan`` | float | | The result is the tangent of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``tanh`` | float | | The result is the hyperbolic tangent of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``toString`` | string | | The decimal representation of the number as a string. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ +| ``ulp`` | float | | The result is the ULP (unit in last place) of the receiver. | ++---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ + +Built-ins for int +~~~~~~~~~~~~~~~~~ + +The following built-in predicates are members of type ``int``: + ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| Name | Result type | Argument types | Content | ++=========================+=============+================+================================================================================================================+ +| ``abs`` | int | | The result is the absolute value of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``acos`` | float | | The result is the inverse cosine of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``asin`` | float | | The result is the inverse sine of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``atan`` | float | | The result is the inverse tangent of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``cos`` | float | | The result is the cosine of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``cosh`` | float | | The result is the hyperbolic cosine of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``exp`` | float | | The result is the value of value of e, the base of the natural logarithm, raised to the power of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``gcd`` | int | int | The result is the greatest common divisor of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``log`` | float | | The result is the natural logarithm of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``log`` | float | float | The result is the logarithm of the receiver with the base of the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``log`` | float | int | The result is the logarithm of the receiver with the base of the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``log10`` | float | | The result is the base-10 logarithm of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``log2`` | float | | The result is the base-2 logarithm of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``maximum`` | float | float | The result is the larger of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``maximum`` | int | int | The result is the larger of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``minimum`` | float | float | The result is the smaller of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``minimum`` | int | int | The result is the smaller of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``pow`` | float | float | The result is the receiver raised to the power of the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``pow`` | float | int | The result is the receiver raised to the power of the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``sin`` | float | | The result is the sine of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``sinh`` | float | | The result is the hyperbolic sine of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``sqrt`` | float | | The result is the square root of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``tan`` | float | | The result is the tangent of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``tanh`` | float | | The result is the hyperbolic tangent of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``bitAnd`` | int | int | The result is the bitwise and of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``bitOr`` | int | int | The result is the bitwise or of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``bitXor`` | int | int | The result is the bitwise xor of the receiver and the argument. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``bitNot`` | int | | The result is the bitwise complement of the receiver. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``bitShiftLeft`` | int | int | The result is the bitwise left shift of the receiver by the argument, modulo 32. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``bitShiftRight`` | int | int | The result is the bitwise right shift of the receiver by the argument, modulo 32. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``bitShiftRightSigned`` | int | int | The result is the signed bitwise right shift of the receiver by the argument, modulo 32. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ +| ``toString`` | string | | The result is the decimal representation of the number as a string. | ++-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ + +The leftmost bit after ``bitShiftRightSigned`` depends on sign extension, whereas after ``bitShiftRight`` it is zero. + +Built-ins for string +~~~~~~~~~~~~~~~~~~~~ + +The following built-in predicates are members of type ``string``: + ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Name | Result type | Argument types | Content | ++======================+=============+==================+========================================================================================================================================================================================================================================================================================================================================================================================+ +| ``charAt`` | string | int | The result is a 1-character string containing the character in the receiver at the index given by the argument. The first element of the string is at index 0. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``indexOf`` | int | string | The result is an index into the receiver where the argument occurs. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``indexOf`` | int | string, int, int | Let the arguments be ``s``, ``n``, and ``start``. The result is the index of occurrence ``n`` of ``substring`` ``s`` in the receiver that is no earlier in the string than ``start``. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``isLowercase`` | | | The receiver contains no upper-case letters. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``isUppercase`` | | | The receiver contains no lower-case letters. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``length`` | int | | The result is the number of characters in the receiver. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``matches`` | | string | The argument is a pattern that matches the receiver, in the same way as the LIKE operator in SQL. Patterns may include ``_`` to match a single character and ``%`` to match any sequence of characters. A backslash can be used to escape an underscore, a percent, or a backslash. Otherwise, all characters in the pattern other than ``_`` and ``%`` and ``\\`` must match exactly. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``prefix`` | string | int | The result is the prefix of the receiver that has a length exactly equal to the argument. If the argument is negative or greater than the receiver's length, then there is no result. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``regexpCapture`` | string | string, int | The receiver exactly matches the regex in the first argument, and the result is the group of the match numbered by the second argument. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``regexpFind`` | string | string, int, int | The receiver contains one or more occurrences of the regex in the first argument. The result is the ``substring`` which matches the regex, the second argument is the occurrence number, and the third argument is the index within the receiver at which the occurrence begins. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``regexpMatch`` | | string | The receiver matches the argument as a regex. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``regexpReplaceAll`` | string | string, string | The result is obtained by replacing all occurrences in the receiver of the first argument as a regex by the second argument. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``replaceAll`` | string | string, string | The result is obtained by replacing all occurrences in the receiver of the first argument by the second. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``splitAt`` | string | string | The result is one of the strings obtained by splitting the receiver at every occurrence of the argument. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``splitAt`` | string | string, int | Let the arguments be ``delim`` and ``i``. The result is field number ``i`` of the fields obtained by splitting the receiver at every occurrence of ``delim``. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``substring`` | string | int, int | The result is the ``substring`` of the receiver starting at the index of the first argument and ending just before the index of the second argument. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``suffix`` | string | int | The result is the suffix of the receiver that has a length exactly equal to the receiver's length minus the argument. If the argument is negative or greater than the receiver's length, then there is no result. As a result, the identity ``s.prefix(i)+s.suffix(i)=s`` holds for ``i`` in ``[0, s.length()]``. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``toDate`` | date | | The result is a date value determined by the receiver. The format of the receiver is unspecified, except that if ``(d, s)`` is in ``date.toString``, ``(s, d)`` is in ``string.toDate``. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``toFloat`` | float | | The result is the float whose value is represented by the receiver. If the receiver cannot be parsed as a float then there is no result. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``toInt`` | int | | The result is the integer whose value is represented by the receiver. If the receiver cannot be parsed as an integer or cannot be represented as a QL ``int``, then there is no result. The parser accepts an optional leading ``-`` or ``+`` character, followed by one or more decimal digits. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``toLowerCase`` | string | | The result is the receiver with all letters converted to lower case. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``toString`` | string | | The result is the receiver. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``toUpperCase`` | string | | The result is the receiver with all letters converted to upper case. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``trim`` | string | | The result is the receiver with all whitespace removed from the beginning and end of the string. | ++----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +Regular expressions are as defined by ``java.util.Pattern`` in Java. + +Evaluation +---------- + +This section specifies the evaluation of a QL program. Evaluation happens in three phases. First, the program is stratified into a number of layers. Second, the layers are evaluated one by one. Finally, the queries in the QL file are evaluated to produce sets of ordered tuples. + +Stratification +~~~~~~~~~~~~~~ + +A QL program can be *stratified* to a sequence of *layers*. A layer is a set of predicates and types. + +A valid stratification must include each predicate and type in the QL program. It must not include any other predicates or types. + +A valid stratification must not include the same predicate in multiple layers. + +Formulas, variable declarations and expressions within a predicate body have a *negation polarity* that is positive, negative, or zero. Positive and negative are opposites of each other, while zero is the opposite of itself. The negation polarity of a formula or expression is then determined as follows: + +- The body of a predicate is positive. + +- The formula within a negation formula has the opposite polarity to that of the negation formula. + +- The condition of a conditional formula has zero polarity. + +- The formula on the left of an implication formula has the opposite polarity to that of the implication. + +- The formula and variable declarations of an aggregate have zero polarity. + +- If the ``monotonicAggregates`` language pragma is not enabled, or the original formula and variable declarations are both omitted, then the expressions and order by expressions of the aggregate have zero polarity. + +- If the ``monotonicAggregates`` language pragma is enabled, and the original formula and variable declarations were not both omitted, then the expressions and order by expressions of the aggregate have the polarity of the aggregate. + +- If a ``forall`` has two quantified formulas, then the first quantified formula has the opposite polarity to that of the ``forall``. + +- The variable declarations of a ``forall`` have the opposite polarity to that of the ``forall``. + +- If a ``forex`` has two quantified formulas, then the first quantified formula has zero polarity. + +- The variable declarations of a ``forex`` have zero polarity. + +- In all other cases, a formula or expression has the same polarity as its immediately enclosing formula or expression. + +For a member predicate ``p`` we define the *strict dispatch dependencies*. The strict dispatch dependencies are defined as: + +- The strict dispatch dependencies of any predicates that override ``p``. +- If ``p`` is not abstract, ``C.class`` for any class ``C`` with a predicate that overrides ``p``. + +For a member predicate ``p`` we define the *dispatch dependencies*. The dispatch dependencies are defined as: + +- The dispatch dependencies of predicates that override ``p``. +- The predicate ``p`` itself. +- ``C.class`` where ``C`` is the class that defines ``p``. + +Predicates, and types can *depend* and *strictly depend* on each other. Such dependencies exist in the following circumstances: + +- If ``A`` strictly depends on ``B``, then ``A`` depends on ``B``. + +- If ``A`` depends on ``B``, then ``A`` also depends on anything on which ``B`` depends. + +- If ``A`` strictly depends on ``B``, then ``A`` and anything depending on ``A`` strictly depend on anything on which ``B`` depends (including ``B`` itself). + +- If a predicate has a parameter whose declared type is a class type ``C``, it depends on ``C.class``. + +- If a predicate declares a result type which is a class type ``C``, it depends on ``C.class``. + +- A member predicate of class ``C`` depends on ``C.class``. + +- If a predicate contains a variable declaration of a variable whose declared type is a class type ``C``, then the predicate depends on ``C.class``. If the declaration has negative or zero polarity then the dependency is strict. + +- If a predicate contains a variable declaration with negative or zero polarity of a variable whose declared type is a class type ``C``, then the predicate strictly depends on ``C.class``. + +- If a predicate contains an expression whose type is a class type ``C``, then the predicate depends on ``C.class``. If the expression has negative or zero polarity then the dependency is strict. + +- A predicate containing a predicate call depends on the predicate to which the call resolves. If the call has negative or zero polarity then the dependency is strict. + +- A predicate containing a predicate call, which resolves to a member predicate and does not have a ``super`` expression as a qualifier, depends on the dispatch dependencies of the root definitions of the target of the call. If the call has negative or zero polarity then the dependencies are strict. The predicate strictly depends on the strict dispatch dependencies of the root definitions. + +- For each class ``C`` in the program, for each base class ``B`` of ``C``, ``C.extends`` depends on ``B.B``. + +- For each class ``C`` in the program, for each base type ``B`` of ``C`` that is not a class type, ``C.extends`` depends on ``B``. + +- For each class ``C`` in the program, ``C.class`` depends on ``C.C``. + +- For each class ``C`` in the program, ``C.C`` depends on ``C.extends``. + +- For each class ``C`` in the program that declares a field of class type ``B``, ``C.C`` depends on ``B.class``. + +- For each class ``C`` with a characteristic predicate, ``C.C`` depends on the characteristic predicate. + +- For each abstract class ``A`` in the program, for each type ``C`` that has ``A`` as a base type, ``A.class`` depends on ``C.class``. + +- A predicate with a higher-order body may strictly depend or depend on each predicate reference within the body. The exact dependencies are left unspecified. + +A valid stratification must have no predicate that depends on a predicate in a later layer. Additionally, it must have no predicate that strictly depends on a predicate in the same layer. + +If a QL program has no valid stratification, then the program itself is not valid. If it does have a stratification, a QL implementation must choose exactly one stratification. The precise stratification chosen is left unspecified. + +Layer evaluation +~~~~~~~~~~~~~~~~ + +The store is first initialized with the *database content* of all built-in predicates and external predicates. The database content of a predicate is a set of ordered tuples that are included in the database. + +Each layer of the stratification is *populated* in order. To populate a layer, each predicate in the layer is repeatedly populated until the store stops changing. The way that a predicate is populated is as follows: + +- To populate a predicate that has a formula as a body, find all named tuples with the variables of the predicate's arguments that match the body formula and the types of the variables. If the predicate has a result, then the matching named tuples should additionally have a value for ``result`` that is in the result type of the predicate. If the predicate is a member predicate, then the tuples should additionally have a value for ``this`` that is of the type assigned to ``this`` by the typing environment. For each such tuple, convert the named tuple to an ordered tuple by sequencing the values of the tuple, starting with ``this`` if present, followed by the predicate's arguments, followed by ``result`` if present. Add each such converted tuple to the predicate in the store. + +- To populate an abstract predicate, do nothing. + +- The population of predicates with a higher-order body is left only partially specified. A number of tuples are added to the given predicate in the store. The tuples that are added must be fully determined by the QL program and by the state of the store. + +- To populate the type ``C.extends`` for a class ``C``, identify each value ``v`` that has the following properties: It is in all non-class base types of ``C``, and for each class base type ``B`` of ``C`` it is in ``B.B``. For each such ``v``, add ``(v)`` to ``C.extends``. + +- To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. Otherwise add each tuple in ``C.extends`` into the store. + +- To populate the type ``C.class`` for a non-abstract class type ``C``, add each tuple in ``C.C`` to ``C.class``. + +- To populate the type ``C.class`` for an abstract class type ``C``, for each class ``D`` that has ``C`` as a base type add all tuples in ``D.class`` to ``C.class``. + +- To populate a select clause, find all named tuples with the variables declared in the ``from`` clause that match the formula given in the ``where`` clause, if there is one. For each named tuple, convert it to a set of ordered tuples where each element of the ordered tuple is, in the context of the named tuple, a value of one of the corresponding select expressions. Collect all ordered tuples that can be produced from all of the restricted named tuples in this way. Add each such converted tuple to the select clause in the store. + +Query evaluation +~~~~~~~~~~~~~~~~ + +A query is evaluated as follows: + +#. Identify all named tuples in the predicate targeted by the query. +#. Sequence the ordered tuples lexicographically. The first elements of the lexicographic order are the tuple elements specified by the ordering directives of the predicate targeted by the query, if it has any. Each such element is ordered either ascending (``asc``) or descending (``desc``) as specified by the ordering directive, or ascending if the ordering directive does not specify. This lexicographic order is only a partial order, if there are fewer ordering directives than elements of the tuples. An implementation may produce any sequence of the ordered tuples that satisfies this partial order. + +Summary of syntax +----------------- + +The complete grammar for QL is as follows: + +:: + + ql ::= moduleBody + + module ::= annotation* "module" modulename "{" moduleBody "}" + + moduleBody ::= (import | predicate | class | module | alias | select)* + + import ::= annotations "import" importModuleId ("as" modulename)? + + qualId ::= simpleId | qualId "." simpleId + + importModuleId ::= qualId + | importModuleId "::" simpleId + + select ::= ("from" var_decls)? ("where" formula)? "select" as_exprs ("order" "by" orderbys)? + + as_exprs ::= as_expr ("," as_expr)* + + as_expr ::= expr ("as" simpleId)? + + orderbys ::= orderby ("," orderby)* + + orderby ::= simpleId ("asc" | "desc")? + + predicate ::= annotations head optbody + + annotations ::= annotation* + + annotation ::= simpleAnnotation | argsAnnotation + + simpleAnnotation ::= "abstract" + | "cached" + | "external" + | "final" + | "transient" + | "library" + | "private" + | "deprecated" + | "override" + | "query" + + argsAnnotation ::= "pragma" "[" ("noinline" | "nomagic" | "noopt") "]" + | "language" "[" "monotonicAggregates" "]" + | "bindingset" "[" (variable ( "," variable)*)? "]" + + head ::= ("predicate" | type) predicateName "(" (var_decls)? ")" + + optbody ::= ";" + | "{" formula "}" + | "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")" + + class ::= annotations "class" classname "extends" type ("," type)* "{" member* "}" + + member ::= character | predicate | field + + character ::= annotations classname "(" ")" "{" formula "}" + + field ::= annotations var_decl ";" + + moduleId ::= simpleId | moduleId "::" simpleId + + type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" + + exprs ::= expr ("," expr)* + + alias := annotations "predicate" literalId "=" predicateRef "/" int ";" + | annotations "class" classname "=" type ";" + | annotations "module" modulename "=" moduleId ";" + + var_decls ::= var_decl ("," var_decl)* + + var_decl ::= type simpleId + + formula ::= fparen + | disjunction + | conjunction + | implies + | ifthen + | negated + | quantified + | comparison + | instanceof + | inrange + | call + + fparen ::= "(" formula ")" + + disjunction ::= formula "or" formula + + conjunction ::= formula "and" formula + + implies ::= formula "implies" formula + + ifthen ::= "if" formula "then" formula "else" formula + + negated ::= "not" formula + + quantified ::= "exists" "(" expr ")" + | "exists" "(" var_decls ("|" formula)? ("|" formula)? ")" + | "forall" "(" var_decls ("|" formula)? "|" formula ")" + | "forex" "(" var_decls ("|" formula)? "|" formula ")" + + comparison ::= expr compop expr + + compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" + + instanceof ::= expr "instanceof" type + + inrange ::= expr "in" range + + call ::= predicateRef (closure)? "(" (exprs)? ")" + | primary "." predicateName (closure)? "(" (exprs)? ")" + + closure ::= "*" | "+" + + expr ::= dontcare + | unop + | binop + | cast + | primary + + + primary ::= eparen + | literal + | variable + | super_expr + | postfix_cast + | callwithresults + | aggregation + | any + | range + | setliteral + + eparen ::= "(" expr ")" + + dontcare ::= "_" + + literal ::= "false" | "true" | int | float | string + + unop ::= "+" expr + | "-" expr + + binop ::= expr "+" expr + | expr "-" expr + | expr "*" expr + | expr "/" expr + | expr "%" expr + + variable ::= varname | "this" | "result" + + super_expr ::= "super" | type "." "super" + + cast ::= "(" type ")" expr + + postfix_cast ::= primary "." "(" type ")" + + aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" + | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" + | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" + + aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" + + aggorderbys ::= aggorderby ("," aggorderby)* + + aggorderby ::= expr ("asc" | "desc")? + + any ::= "any" "(" var_decls ("|" (formula)? ("|" expr)?)? ")" + + callwithresults ::= predicateRef (closure)? "(" (exprs)? ")" + | primary "." predicateName (closure)? "(" (exprs)? ")" + + range ::= "[" expr ".." expr "]" + + setliteral ::= "[" expr ("," expr)* "]" + + simpleId ::= lowerId | upperId + + modulename ::= simpleId + + classname ::= upperId + + dbasetype ::= atLowerId + + predicateRef ::= (moduleId "::")? literalId + + predicateName ::= lowerId + + varname ::= simpleId + + literalId ::= lowerId | atLowerId | "any" | "none" diff --git a/docs/language/ql-handbook/qldoc.rst b/docs/language/ql-handbook/qldoc.rst new file mode 100644 index 00000000000..d2ca924598e --- /dev/null +++ b/docs/language/ql-handbook/qldoc.rst @@ -0,0 +1,50 @@ +QLDoc comment specification +=========================== + +This document is a formal specification for QLDoc comments. + +About QLDoc comments +-------------------- + +You can provide documentation for a QL entity by adding a QLDoc comment in the source file. The QLDoc comment is displayed as pop-up information in QL editors, for example when you hover over a predicate name. + +Notation +-------- + +A 'QLDoc comment' is a valid QL comment that begins with ``/**`` and ends with ``*/``. + +The 'content' of a QLDoc comment is the textual body of the comment, omitting the initial ``/**``, the trailing ``*/``, and the leading whitespace followed by ``*`` on each internal line. + +A QLDoc comment 'precedes' the next QL syntax element after it in the file. + +Association +----------- + +A QLDoc comment may be 'associated with' any of the following QL syntax elements: + +- Class declarations +- Non-member predicate declarations +- Member predicate declarations +- Modules + +For class and predicate declarations, the associated QLDoc comment (if any) is the closest preceding QLDoc comment. + +For modules, the associated QLDoc comment (if any) is the QLDoc comment which is the first element in the file, and moreover is not associated with any other QL element. + +Inheritance +----------- + +If a member predicate has no directly associated QLDoc and overrides a set of member predicates which all have the same QLDoc, then the member predicate inherits that QLDoc. + +Content +------- + +The content of a QLDoc comment is interpreted as standard Markdown, with the following extensions: + +- Fenced code blocks using backticks. +- Automatic interpretation of links and email addresses. +- Use of appropriate characters for ellipses, dashes, apostrophes, and quotes. + +The content of a QLDoc comment may contain metadata tags as follows: + +The tag begins with any number of whitespace characters, followed by an '@' sign. At this point there may be any number of non-whitespace characters, which form the key of the tag. Then, a single whitespace character which separates the key from the value. The value of the tag is formed by the remainder of the line, and any subsequent lines until another '@' tag is seen, or the end of the content is reached. From c08f730bcddd6d8b76dd6e32de456ce0580dd875 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 1 Apr 2020 11:51:57 +0100 Subject: [PATCH 232/459] Delete "About QL" and references to it --- docs/language/learn-ql/about-ql.rst | 69 ------------------- docs/language/learn-ql/index.rst | 1 - docs/language/learn-ql/introduction-to-ql.rst | 2 +- .../slide-snippets/intro-ql-general.rst | 2 +- 4 files changed, 2 insertions(+), 72 deletions(-) delete mode 100644 docs/language/learn-ql/about-ql.rst diff --git a/docs/language/learn-ql/about-ql.rst b/docs/language/learn-ql/about-ql.rst deleted file mode 100644 index 5f5362b8fd8..00000000000 --- a/docs/language/learn-ql/about-ql.rst +++ /dev/null @@ -1,69 +0,0 @@ -About QL -======== - -This section is aimed at users with a background in general purpose programming as well as in databases. For a basic introduction and information on how to get started, see :doc:`Introduction to QL ` and :doc:`Learning CodeQL <../index>`. - -QL is a declarative, object-oriented query language that is optimized to enable efficient analysis of hierarchical data structures, in particular, databases representing software artifacts. - -The queries and metrics used in LGTM are implemented using CodeQL, which uses QL to analyze code. This ensures that they can be extended or revised easily to keep up with changes in definitions of best coding practice. We continually improve existing queries as we work towards the ultimate goal of 100% precision. - -You can write queries to identify security vulnerabilities, find coding errors and bugs, or find code that breaks your team's guidelines for best practice. You can also create customized versions of the default queries to accommodate a new framework. - -About query languages and databases ------------------------------------ - -A database is an organized collection of data. The most commonly used database model is a relational model which stores data in tables and SQL (Structured Query Language) is the most commonly used query language for relational databases. - -The purpose of a query language is to provide a programming platform where you can ask questions about information stored in a database. A database management system manages the storage and administration of data and provides the querying mechanism. A query typically refers to the relevant database entities and specifies various conditions (called predicates) that must be satisfied by the results. Query evaluation involves checking these predicates and generating the results. Some of the desirable properties of a good query language and its implementation include: - -- Declarative specifications - a declarative specification describes properties that the result must satisfy, rather than providing the procedure to compute the result. In the context of database query languages, declarative specifications abstract away the details of the underlying database management system and query processing techniques. This greatly simplifies query writing. -- Expressiveness - a powerful query language allows you to write complex queries. This makes the language widely applicable. -- Efficient execution - queries can be complex and databases can be very large, so it is crucial for a query language implementation to process and execute queries efficiently. - -Properties of QL ----------------- - -The syntax of QL is similar to SQL, but the semantics of QL are based on Datalog, a declarative logic programming language often used as a query language. This makes QL primarily a logic language, and all operations in QL are logical operations. Furthermore, QL inherits recursive predicates from Datalog, and adds support for aggregates, making even complex queries concise and simple. For example, consider a database containing parent-child relationships for people. If we want to find the number of descendants of a person, typically we would: - -#. Find a descendant of the given person, that is, a child or a descendant of a child. -#. Count the number of descendants found using the previous step. - -When you write this process in QL, it closely resembles the above structure. Notice that we used recursion to find all descendants of the given person, and an aggregate to count the number of descendants. Translating these steps into the final query without adding any procedural details is possible due to the declarative nature of the language. The QL code would look something like this: - -.. code-block:: ql - - Person getADescendant(Person p) { - result = p.getAChild() or - result = getADescendant(p.getAChild()) - } - - int getNumberOfDescendants(Person p) { - result = count(getADescendant(p)) - } - -QL and object orientation -------------------------- - -Object orientation is an important feature of QL. The benefits of object orientation are well known – it increases modularity, enables information hiding, and allows code reuse. QL offers all these benefits without compromising on its logical foundation. This is achieved by defining a simple object model where classes are modeled as predicates and inheritance as implication. The libraries made available for all supported languages make extensive use of classes and inheritance. - -QL and general purpose programming languages --------------------------------------------- - -Here are a few prominent conceptual and functional differences between general purpose programming languages and QL: - -- QL does not have any imperative features such as assignments to variables or file system operations. -- QL operates on sets of tuples and a query can be viewed as a complex sequence of set operations that defines the result of the query. -- QL's set-based semantics makes it very natural to process collections of values without having to worry about efficiently storing, indexing and traversing them. -- In object oriented programming languages, instantiating a class involves creating an object by allocating physical memory to hold the state of that instance of the class. In QL, classes are just logical properties describing sets of already existing values. - -These topics are discussed in detail in the `QL language handbook `__. - -References ----------- - -Academic references available from the `Semmle website `__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: - -- `Database theory: Query languages `__ -- `Logic Programming and Databases book - Amazon page `__ -- `Foundations of Databases `__ -- `Datalog `__ diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index dd74ebdc0a9..4d7f4590721 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -19,7 +19,6 @@ CodeQL is based on a powerful query language called QL. The following topics hel :maxdepth: 1 introduction-to-ql - about-ql beginner/ql-tutorials writing-queries/writing-queries cpp/ql-for-cpp diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index e6ff509f570..b09fee8241d 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -165,4 +165,4 @@ Learning CodeQL - To find out more about how to write your own queries, try working through the :doc:`QL tutorials `. - For an overview of the other available resources, see :doc:`Learning CodeQL <../index>`. -- For a more technical description of the underlying language, see :doc:`About QL `. +- For a more technical description of the underlying language, see the `QL language reference `__ \ No newline at end of file diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index 8d6a25afad7..2dc64517465 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -124,7 +124,7 @@ QL is: .. note:: - QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting `Introduction to the QL language `__ and `About QL `__. + QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting the `QL language reference `__. The key features of QL are: - All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables. From 27408c258443034bf3c441a06c01d9f42b902b45 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 1 Apr 2020 12:03:00 +0100 Subject: [PATCH 233/459] Delete QL spec articles and add README --- docs/language/ql-spec/index.rst | 27 +- docs/language/ql-spec/language.rst | 2013 ---------------------------- docs/language/ql-spec/qldoc.rst | 50 - 3 files changed, 4 insertions(+), 2086 deletions(-) delete mode 100644 docs/language/ql-spec/language.rst delete mode 100644 docs/language/ql-spec/qldoc.rst diff --git a/docs/language/ql-spec/index.rst b/docs/language/ql-spec/index.rst index e132d3ecac5..cba06a87746 100644 --- a/docs/language/ql-spec/index.rst +++ b/docs/language/ql-spec/index.rst @@ -1,24 +1,5 @@ -QL specifications -################# +README +###### -.. index:: specification - - -For a formal specification of the QL language, including a description of syntax, terminology, and other technical details, please consult the QL language specification. - -For information on the terminology and syntax used in QLDoc comments, please consult the QLDoc comment specification. - -.. toctree:: - :maxdepth: 2 - - language - - qldoc - - -Search -****** - -.. * :ref:`genindex` - -* :ref:`search` +The specifications have moved to ``ql/docs/language/ql-handbook``. +See https://github.com/github/semmle-docs/issues/21 for details of the restructuring. \ No newline at end of file diff --git a/docs/language/ql-spec/language.rst b/docs/language/ql-spec/language.rst deleted file mode 100644 index 2853c6ed899..00000000000 --- a/docs/language/ql-spec/language.rst +++ /dev/null @@ -1,2013 +0,0 @@ -QL language specification -========================= - -This is a formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. - -Introduction ------------- - -QL is a query language for CodeQL databases. The data is relational: named relations hold sets of tuples. The query language is a dialect of Datalog, using stratified semantics, and it includes object-oriented classes. - -Notation --------- - -This section describes the notation used in the specification. - -Unicode characters -~~~~~~~~~~~~~~~~~~ - -Unicode characters in this document are described in two ways. One is to supply the character inline in the text, between double quote marks. The other is to write a capital U, followed by a plus sign, followed by a four-digit hexadecimal number representing the character's code point. As an example of both, the first character in the name QL is "Q" (U+0051). - -Grammars -~~~~~~~~ - -The syntactic forms of QL constructs are specified using a modified Backus-Naur Form (BNF). Syntactic forms, including classes of tokens, are named using bare identifiers. Quoted text denotes a token by its exact sequence of characters in the source code. - -BNF derivation rules are written as an identifier naming the syntactic element, followed by ``::=``, followed by the syntax itself. - -In the syntax itself, juxtaposition indicates sequencing. The vertical bar (``|``, U+007C) indicates alternate syntax. Parentheses indicate grouping. An asterisk (``*``, U+002A) indicates repetition zero or more times, and a plus sign (``+``, U+002B) indicates repetition one or more times. Syntax followed by a question mark (``?``, U+003F) indicates zero or one occurrences of that syntax. - -Architecture ------------- - -A *QL program* consists of a query module defined in a QL file and a number of library modules defined in QLL files that it imports (see `Import directives <#import-directives>`__). The module in the QL file includes one or more queries (see `Queries <#queries>`__). A module may also include *import directives* (see `Import directives <#import-directives>`__), non-member predicates (see `Non-member predicates <#non-member-predicates>`__), class definitions (see `Classes <#classes>`__), and module definitions (see `Modules <#modules>`__). - -QL programs are interpreted in the context of a *database* and a *library path* . The database provides a number of definitions: database types (see `Types <#types>`__), entities (see `Values <#values>`__), built-in predicates (see `Built-ins <#built-ins>`__), and the *database content* of built-in predicates and external predicates (see `Evaluation <#evaluation>`__). The library path is a sequence of file-system directories that hold QLL files. - -A QL program can be *evaluated* (see `Evaluation <#evaluation>`__) to produce a set of tuples of values (see `Values <#values>`__). - -For a QL program to be *valid*, it must conform to a variety of conditions that are described throughout this specification; otherwise the program is said to be *invalid*. An implementation of QL must detect all invalid programs and refuse to evaluate them. - -Name resolution ---------------- - -All modules have three environments that dictate name resolution. These are multimaps of keys to declarations. - -The environments are: - -- The *module environment*, whose keys are module names and whose values are modules. -- The *type environment*, whose keys are type names and whose values are types. -- The *predicate environment*, whose keys are pairs of predicate names and arities and whose values are predicates. - -If not otherwise specified, then the environment for a piece of syntax is the same as the environment of its enclosing syntax. - -When a key is resolved in an environment, if there is no value for that key, then the program is invalid. - -Environments may be combined as follows: - -- *Union*. This takes the union of the entry sets of the two environments. -- *Overriding union*. This takes the union of two environments, but if there are entries for a key in the first map, then no additional entries for that key are included from the second map. - -A *definite* environment has at most one entry for each key. Resolution is unique in a definite environment. - -Global environments -~~~~~~~~~~~~~~~~~~~ - -The global module environment is empty. - -The global type environment has entries for the primitive types ``int``, ``float``, ``string``, ``boolean``, and ``date``, as well as any types defined in the database schema. - -The global predicate environment includes all the built-in classless predicates, as well as any extensional predicates declared in the database schema. - -The program is invalid if any of these environments is not definite. - -Module environments -~~~~~~~~~~~~~~~~~~~ - -For each of modules, types, and predicates, a module *imports*, *declares*, and *exports* an environment. These are defined as follows (with X denoting the type of entity we are currently considering): - -- The *imported X environment* of a module is defined to be the union of the exported X environments of all the modules which the current module directly imports (see `Import directives <#import-directives>`__). - -- The *declared X environment* of a module is the multimap of X declarations in the module itself. - -- The *exported X environment* of a module is the union of the exported X environments of the modules which the current module directly imports (excluding ``private`` imports), and the declared X environment of the current module (excluding ``private`` declarations). - -- The *external X environment* of a module is the visible X environment of the enclosing module, if there is one, and otherwise the global X environment. - -- The *visible X environment* is the union of the imported X environment, the declared X environment, and the external X environment. - -The program is invalid if any of these environments is not definite. - -Module definitions may be recursive, so the module environments are defined as the least fixed point of the operator given by the above definition. Since all the operations involved are monotonic, this fixed point exists and is unique. - -Modules -------- - -Module definitions -~~~~~~~~~~~~~~~~~~ - -A QL module definition has the following syntax: - -:: - - module ::= annotation* "module" modulename "{" moduleBody "}" - - moduleBody ::= (import | predicate | class | module | alias | select)* - -A module definition extends the current module's declared module environment with a mapping from the module name to the module definition. - -QL files consist of simply a module body without a name and surrounding braces: - -:: - - ql ::= moduleBody - -QL files define a module corresponding to the file, whose name is the same as the filename. - -Kinds of modules -~~~~~~~~~~~~~~~~ - -A module may be: - -- A *file module*, if it is defined implicitly by a QL file. -- A *query module*, if it is defined by a QL file. -- A *library module*, if it is not a query module. - -A query module must contain one or more queries. - -Import directives -~~~~~~~~~~~~~~~~~ - -An import directive refers to a module identifier: - -:: - - import ::= annotations "import" importModuleId ("as" modulename)? - - qualId ::= simpleId | qualId "." simpleId - - importModuleId ::= qualId - | importModuleId "::" simpleId - -An import directive may optionally name the imported module using an ``as`` declaration. If a name is defined, then the import directive adds to the declared module environment of the current module a mapping from the name to the declaration of the imported module. Otherwise, the current module *directly imports* the imported module. - -Module resolution -~~~~~~~~~~~~~~~~~ - -Module identifiers are resolved to modules as follows. - -For simple identifiers: - -- First, the identifier is resolved as a one-segment qualified identifier (see below). - -- If this fails, the identifier is resolved in the current module's visible module environment. - -For selection identifiers (``a::b``): - -- The qualifier of the selection (``a``) is resolved as a module, and then the name (``b``) is resolved in the exported module environment of the qualifier module. - -For qualified identifiers (``a.b``): - -- Define the *current file* as the file the import directive occurs in. - -- Determine the current file's *query directory*, if any. Starting with the directory containing the current file, and walking up the directory structure, each directory is checked for a file called ``queries.xml``, containing a single top-level tag named ``queries``, which has a ``language`` attribute set to the identifier of the active database scheme (for example, ````). The closest enclosing directory is taken as the current file's query directory. - -- Build up a list of *candidate search paths*, consisting of the current file's directory, the current file's query directory (if one was determined in the previous step), and the list of directories making up the library path (in order). - -- Determine the first candidate search path that has a *matching* QLL file for the import directive's qualified name. A QLL file in a candidate search path is said to match a qualified name if, starting from the candidate search path, there is a subdirectory for each successive qualifier in the qualified name, and the directory named by the final qualifier contains a file whose base name matches the qualified name's base name, with the addition of the file extension ``.qll``. The file and directory names are matched case-sensitively, regardless of whether the filesystem is case-sensitive or not. - -- The resolved module is the module defined by the selected candidate search path. - -A qualified module identifier is only valid within an import. - -Module references and active modules -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A module ``M`` *references* another module ``N`` if any of the following holds: - -- ``M`` imports ``N``. -- ``M`` defines ``N``. -- ``N`` is ``M``'s enclosing module. - -In a QL program, the *active* modules are the modules which are referenced transitively by the query module. - -Types ------ - -QL is a typed language. This section specifies the kinds of types available, their attributes, and the syntax for referring to them. - -Kinds of types -~~~~~~~~~~~~~~ - -Types in QL are either *primitive* types, *database* types, *class* types, *character* types or *class domain* types. - -The primitive types are ``boolean``, ``date``, ``float``, ``int``, and ``string``. - -Database types are supplied as part of the database. Each database type has a *name*, which is an identifier starting with an at sign (``@``, U+0040) followed by lower-case letter. Database types have some number of *base types*, which are other database types. In a valid database, the base types relation is non-cyclic. - -Class types are defined in QL, in a way specified later in this document (see `Classes <#classes>`__). Each class type has a name that is an identifier starting with an upper-case letter. Each class type has one or more base types, which can be any kind of type except a class domain type. A class type may be declared *abstract*. - -Any class in QL has an associated class domain type and an associated character type. - -Within the specification the class type for ``C`` is written ``C.class``, the character type is written ``C.C`` and the domain type is written ``C.extends``. However the class type is still named ``C``. - -Type references -~~~~~~~~~~~~~~~ - -With the exception of class domain types and character types (which cannot be referenced explicitly in QL source), a reference to a type is written as the name of the type. In the case of database types, the name includes the at sign (``@``, U+0040). - -:: - - type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" - - moduleId ::= simpleId | moduleId "::" simpleId - -A type reference is resolved to a type as follows: - -- If it is a selection identifier (for example, ``a::B``), then the qualifier (``a``) is resolved as a module (see `Module resolution <#module-resolution>`__). The identifier (``B``) is then resolved in the exported type environment of the qualifier module. - -- Otherwise, the identifier is resolved in the current module's visible type environment. - -Relations among types -~~~~~~~~~~~~~~~~~~~~~ - -Types are in a subtype relationship with each other. Type A is a *subtype* of type B if one of the following is true: - -- A and B are the same type. - -- There is some type C, where A is a subtype of C and C is a subtype of B. - -- A and B are database types, and B is a base type of A. - -- A is the character type of C, and B is the class domain type of C. - -- A is a class type, and B is the character type of A. - -- A is a class domain type, and B is a base type of the associated class type. - -- A is ``int`` and B is ``float``. - -Supertypes are the converse of subtypes: A is a *supertype* of B if B is a subtype of A. - -Types A and B are *compatible* with each other if they either have a common supertype, or they each have some supertype that is a database type. - -Typing environments -~~~~~~~~~~~~~~~~~~~ - -A *typing environment* is a finite map of variables to types. Each variable in the map is either an identifier or one of two special symbols: ``this``, and ``result``. - -Most forms of QL syntax have a typing environment that applies to them. That typing environment is determined by the context the syntax appears in. - -Note that this is distinct from the type environment, which is a map from type names to types. - -Active types -~~~~~~~~~~~~ - -In a QL program, the *active* types are those defined in active modules. In the remainder of this specification, any reference to the types in the program refers only to the active types. - -Values ------- - -Values are the fundamental data that QL programs compute over. This section specifies the kinds of values available in QL, specifies the sorting order for them, and describes how values can be combined into tuples. - -Kinds of values -~~~~~~~~~~~~~~~ - -There are six kinds of values in QL: one kind for each of the five primitive types, and *entities*. Each value has a type. - -A boolean value is of type ``boolean``, and may have one of two distinct values: ``true`` or ``false``. - -A date value is of type ``date``. It encodes a time and a date in the Gregorian calendar. Specifically, it includes a year, a month, a day, an hour, a minute, a second, and a millisecond, each of which are integers. The year ranges from -16777216 to 16777215, the month from 0 to 11, the day from 1 to 31, the hour from 0 to 23, the minutes from 0 to 59, the seconds from 0 to 59, and the milliseconds from 0 to 999. - -A float value is of type ``float``. Each float value is a binary 64-bit floating-point value as specified in IEEE 754. - -An integer value is of type ``int``. Each value is a 32-bit two's complement integer. - -A string is a finite sequence of 16-bit characters. The characters are interpreted as Unicode code points. - -The database includes a number of opaque entity values. Each such value has a type that is one of the database types, and an identifying integer. An entity value is written as the name of its database type followed by its identifying integer in parentheses. For example, ``@tree(12)``, ``@person(16)``, and ``@location(38132)`` are entity values. The identifying integers are left opaque to programmers in this specification, so an implementation of QL is free to use some other set of countable labels to identify its entities. - -Ordering -~~~~~~~~ - -Values in general do not have a specified ordering. In particular, entity values have no specified ordering with entities or any other values. Primitive values, however, have a total ordering with other primitive values in the same type. Primitives types and their subtypes are said to be *orderable*. - -For booleans, ``false`` is ordered before ``true``. - -For dates, the ordering is chronological. - -For floats, the ordering is as specified in IEEE 754 when one exists, except that NaN is considered equal to itself and is ordered after all other floats, and negative zero is considered to be strictly less than positive zero. - -For integers, the ordering is as for two's complement integers. - -For strings, the ordering is lexicographic. - -Tuples -~~~~~~ - -Values can be grouped into tuples in two different ways. - -An *ordered tuple* is a finite, ordered sequence of values. For example, (``1``, ``2``, ``"three"``) is an ordered sequence of two integers and a string. - -A *named tuple* is a finite map of variables to values. Each variable in a named tuple is either an identifier, ``this``, or ``result``. - -A *variable declaration list* provides a sequence of variables and a type for each one: - -:: - - var_decls ::= var_decl ("," var_decl)* - var_decl ::= type simpleId - -A valid variable declaration list must not include two declarations with the same variable name. Moreover, if the declaration has a typing environment that applies, it must not use a variable name that is already present in that typing environment. - -An *extension* of a named tuple for a given variable declaration list is a named tuple that additionally maps each variable in the list to a value. The value mapped by each new variable must be in the type that is associated with that variable in the given list; see `The store <#the-store>`__ for the definition of a value being in a type. - -The store ---------- - -QL programs evaluate in the context of a *store*. This section specifies several definitions related to the store. - -A *fact* is a predicate or type along with an ordered tuple. A fact is written as the predicate name or type name followed immediately by the tuple. Here are some examples of facts: - -:: - - successor(0, 1) - Tree.toString(@method_tree(12), "def println") - Location.class(@location(43)) - Location.getURL(@location(43), "file:///etc/hosts:2:0:2:12") - -A *store* is a mutable set of facts. The store can be mutated by adding more facts to it. - -An ordered tuple *directly satisfies* a predicate or type with a given if there is a fact in the store with the given tuple and predicate or type. - -A value ``v`` is in a type ``t`` under any of the following conditions: - -- The type of ``v`` is ``t`` and ``t`` is a primitive type. -- The tuple ``(v)`` directly satisfies ``t``. - -An ordered tuple *satisfies a predicate* ``p`` under the following circumstances. If ``p`` is not a member predicate, then the tuple satisfies the predicate whenever it directly satisfies the predicate. - -Otherwise, the tuple must be the tuple of a fact in the store with predicate ``q``, where ``q`` has the same root definition as ``p``. The first element of the tuple must be in the type before the dot in ``q``, and there must be no other predicate that overrides ``q`` such that this is true (see `Classes <#classes>`__ for details on overriding and root definitions). - -An ordered tuple ``(a0, an)`` satisfies the ``+`` closure of a predicate if there is a sequence of binary tuples ``(a0, a1)``, ``(a1, a2)``, ..., ``(an-1, an)`` that all satisfy the predicate. An ordered tuple ``(a, b)`` satisfies the ``*`` closure of a predicate if it either satisfies the ``+`` closure, or if ``a`` and ``b`` are the same, and if moreover they are in each argument type of the predicate. - -Lexical syntax --------------- - -QL and QLL files contain a sequence of *tokens* that are encoded as Unicode text. This section describes the tokenization algorithm, the kinds of available tokens, and their representation in Unicode. - -Some kinds of tokens have an identifier given in parentheses in the section title. That identifier, if present, is a terminal used in grammar productions later in the specification. Additionally, the `Identifiers <#identifiers>`__ section gives several kinds of identifiers, each of which has its own grammar terminal. - -Tokenization -~~~~~~~~~~~~ - -Source files are interpreted as a sequence of tokens according to the following algorithm. First, the longest-match rule, described below, is applied starting at the beginning of the file. Second, all whitespace tokens and comments are discarded from the sequence. - -The longest-match rule is applied as follows. The first token in the file is the longest token consisting of a contiguous sequence of characters at the beginning of the file. The next token after any other token is the longest token consisting of contiguous characters that immediately follow any previous token. - -If the file cannot be tokenized in its entirety, then the file is invalid. - -Whitespace -~~~~~~~~~~ - -A whitespace token is a sequence of spaces (U+0020), tabs (U+0009), carriage returns (U+000D), and line feeds (U+000A). - -Comments -~~~~~~~~ - -There are two kinds of comments in QL: one-line and multiline. - -A one-line comment is two slash characters (``/``, U+002F) followed by any sequence of characters other than line feeds (U+000A) and carriage returns (U+000D). Here is an example of a one-line comment: - -:: - - // This is a comment - -A multiline comment is a *comment start*, followed by a *comment body*, followed by a *comment end*. A comment start is a slash (``/``, U+002F) followed by an asterisk (``*``, U+002A), and a comment end is an asterisk followed by a slash. A comment body is any sequence of characters that does not include a comment end. Here is an example multiline comment: - -:: - - /* - It was the best of code. - It was the worst of code. - It had a multiline comment. - */ - -Keywords -~~~~~~~~ - -The following sequences of characters are keyword tokens: - -:: - - and - any - as - asc - avg - boolean - by - class - concat - count - date - desc - else - exists - extends - false - float - forall - forex - from - if - implies - import - in - instanceof - int - max - min - module - none - not - or - order - predicate - rank - result - select - strictconcat - strictcount - strictsum - string - sum - super - then - this - true - where - -Operators -~~~~~~~~~ - -The following sequences of characters are operator tokens: - -:: - - < - <= - = - > - >= - _ - - - , - ; - != - / - . - .. - ( - ) - [ - ] - { - } - * - % - + - | - -Identifiers -~~~~~~~~~~~ - -An identifier is an optional "@" sign (U+0040) followed by a sequence of identifier characters. Identifier characters are lower-case ASCII letters (``a`` through ``z``, U+0061 through U+007A), upper-case ASCII letters (``A`` through ``Z``, U+0041 through U+005A), decimal digits (``0`` through ``9``, U+0030 through U+0039), and underscores (``_``, U+005F). The first character of an identifier other than any "@" sign must be a letter. - -An identifier cannot have the same sequence of characters as a keyword, nor can it be an "@" sign followed by a keyword. - -Here are some examples of identifiers: - -:: - - width - Window_width - window5000_mark_II - @expr - -There are several kinds of identifiers: - -- ``lowerId``: an identifier that starts with a lower-case letter. - -- ``upperId``: an identifier that starts with an upper-case letter. - -- ``atLowerId``: an identifier that starts with an "@" sign and then a lower-case letter. - -- ``atUpperId``: an identifier that starts with an "@" sign and then an upper-case letter. - -Identifiers are used in following syntactic constructs: - -:: - - simpleId ::= lowerId | upperId - modulename ::= simpleId - classname ::= upperId - dbasetype ::= atLowerId - predicateRef ::= (moduleId "::")? literalId - predicateName ::= lowerId - varname ::= simpleId - literalId ::= lowerId | atLowerId - -Integer literals (int) -~~~~~~~~~~~~~~~~~~~~~~ - -An integer literal is a possibly negated sequence of decimal digits (``0`` through ``9``, U+0030 through U+0039). Here are some examples of integer literals: - -:: - - 0 - 42 - 123 - -2147483648 - -Float literals (float) -~~~~~~~~~~~~~~~~~~~~~~ - -A floating-point literals is a possibly negated two non-negative integers literals separated by a dot (``.``, U+002E). Here are some examples of float literals: - -:: - - 0.5 - 2.0 - 123.456 - -100.5 - -String literals (string) -~~~~~~~~~~~~~~~~~~~~~~~~ - -A string literal denotes a sequence of characters. It begins and ends with a double quote character (U+0022). In between the double quotes are a sequence of string character indicators, each of which indicates one character that should be included in the string. The string character indicators are as follows. - -- Any character other than a double quote (U+0022), backslash (U+005C), line feed (U+000A), carriage return (U+000D), or tab (U+0009). Such a character indicates itself. - -- A backslash (U+005C) followed by one of the following characters: - - - Another backslash (U+005C), in which case a backslash character is indicated. - - A double quote (U+0022), in which case a double quote is indicated. - - The letter "n" (U+006E), in which case a line feed (U+000A) is indicated. - - The letter "r" (U+0072), in which case a carriage return (U+000D) is indicated. - - The letter "t" (U+0074), in which case a tab (U+0009) is indicated. - -Here are some examples of string literals: - -:: - - "hello" - "He said, \"Logic clearly dictates that the needs of the many...\"" - -Annotations ------------ - -Various kinds of syntax can have *annotations* applied to them. Annotations are as follows: - -:: - - annotations ::= annotation* - - annotation ::= simpleAnnotation | argsAnnotation - - simpleAnnotation ::= "abstract" - | "cached" - | "external" - | "final" - | "transient" - | "library" - | "private" - | "deprecated" - | "override" - | "query" - - argsAnnotation ::= "pragma" "[" ("inline" | "noinline" | "nomagic" | "noopt") "]" - | "language" "[" "monotonicAggregates" "]" - | "bindingset" "[" (variable ( "," variable)*)? "]" - -Each simple annotation adds a same-named attribute to the syntactic entity it precedes. For example, if a class is preceded by the ``abstract`` annotation, then the class is said to be abstract. - -A valid annotation list may not include the same simple annotation more than once, or the same parameterized annotation more than once with the same arguments. However, it may include the same parameterized annotation more than once with different arguments. - -Simple annotations -~~~~~~~~~~~~~~~~~~ - -The following table summarizes the syntactic constructs which can be marked with each annotation in a valid program; for example, an ``abstract`` annotation preceding a character is invalid. - -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| Annotation | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | -+================+=========+============+===================+=======================+=========+========+=========+=========+ -| ``abstract`` | yes | | yes | | | | | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``cached`` | yes | yes | yes | yes | | | yes | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``external`` | | | | yes | | | | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``final`` | yes | | yes | | | yes | | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``transient`` | | | | yes | | | | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``library`` | yes | | | | | | | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``private`` | yes | | yes | yes | yes | yes | yes | yes | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``deprecated`` | yes | | yes | yes | | yes | yes | yes | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``override`` | | | yes | | | yes | | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``query`` | | | | yes | | | | yes | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ - -The ``library`` annotation is only usable within a QLL file, not a QL file. - -Annotations on aliases apply to the name introduced by the alias. An alias may, for example, have different privacy to the name it aliases. - -Parameterized annotations -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Parameterized annotations take some additional arguments. - -The parameterized annotation ``pragma`` supplies compiler pragmas, and may be applied in various contexts depending on the pragma in question. - -+--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| Pragma | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | -+==============+=========+============+===================+=======================+=========+========+=========+=========+ -| ``inline`` | | yes | yes | yes | | | | | -+--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``noinline`` | | yes | yes | yes | | | | | -+--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``nomagic`` | | yes | yes | yes | | | | | -+--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| ``noopt`` | | yes | yes | yes | | | | | -+--------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ - -The parameterized annotation ``language`` supplies language pragmas which change the behavior of the language. Language pragmas apply at the scope level, and are inherited by nested scopes. - -+-------------------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| Pragma | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | -+=========================+=========+============+===================+=======================+=========+========+=========+=========+ -| ``monotonicAggregates`` | yes | yes | yes | yes | | | yes | | -+-------------------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ - -A binding set for a predicate is a subset of the predicate’s arguments such that if those arguments are bound (restricted to a finite range of values), then all of the predicate’s arguments are bound. - -The parameterized annotation ``bindingset`` can be applied to a predicate (see `Non-member predicates <#non-member-predicates>`__ and `Members <#members>`__) to specify a binding set. - -This annotation accepts a (possibly empty) list of variable names as parameters. The named variables must all be arguments of the predicate, possibly including ``this`` for characteristic predicates and member predicates, and ``result`` for predicates that yield a result. - -In the default case where no binding sets are specified by the user, then it is assumed that there is precisely one, empty binding set - that is, the body of the predicate must bind all the arguments. - -Binding sets are checked by the QL compiler in the following way: - -#. It assumes that all variables mentioned in the binding set are bound. -#. It checks that, under this assumption, all the remaining argument variables are bound by the predicate body. - -A predicate may have several different binding sets, which can be stated by using multiple ``bindingset`` annotations on the same predicate. - -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ -| Pragma | Classes | Characters | Member predicates | Non-member predicates | Imports | Fields | Modules | Aliases | -+================+=========+============+===================+=======================+=========+========+=========+=========+ -| ``bindingset`` | | yes | yes | yes | | | | | -+----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ - -Top-level entities ------------------- - -Modules include five kinds of top-level entity: predicates, classes, modules, aliases, and select clauses. - -Non-member predicates -~~~~~~~~~~~~~~~~~~~~~ - -A *predicate* is declared as a sequence of annotations, a head, and an optional body: - -:: - - predicate ::= annotations head optbody - -A predicate definition adds a mapping from the predicate name and arity to the predicate declaration to the current module's declared predicate environment. - -When a predicate is a top-level clause in a module, it is called a non-member predicate. See below for `member predicates <#member-predicates>`__. - -A valid non-member predicate can be annotated with ``cached``, ``deprecated``, ``external``, ``transient``, ``private``, and ``query``. Note, the ``transient`` annotation can only be applied if the non-member predicate is also annotated with ``external``. - -The head of the predicate gives a name, an optional *result type*, and a sequence of variables declarations that are *arguments*: - -:: - - head ::= ("predicate" | type) predicateName "(" (var_decls)? ")" - -The body of a predicate is of one of three forms: - -:: - - optbody ::= ";" - | "{" formula "}" - | "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")" - -In the first form, with just a semicolon, the predicate is said to not have a body. In the second form, the body of the predicate is the given formula (see `Formulas <#formulas>`__). In the third form, the body is a higher-order relation. - -A valid non-member predicate must have a body, either a formula or a higher-order relation, unless it is external, in which case it must not have a body. - -The typing environment for the body of the formula, if present, maps the variables in the head of the predicate to their associated types. If the predicate has a result type, then the typing environment also maps ``result`` to the result type. - -Classes -~~~~~~~ - -A class definition has the following syntax: - -:: - - class ::= annotations "class" classname "extends" type ("," type)* "{" member* "}" - -The identifier following the ``class`` keyword is the name of the class. - -The types specified after the ``extends`` keyword are the *base types* of the class. - -A class domain type is said to *inherit* from the base types of the associated class type, a character type is said to *inherit* from its associated class domain type and a class type is said to *inherit* from its associated character type. In addition, inheritance is transitive: If a type ``A`` inherits from a type ``B``, and ``B`` inherits from a type ``C``, then ``A`` inherits from ``C``. - -A class adds a mapping from the class name to the class declaration to the current module's declared type environment. - -A valid class can be annotated with ``abstract``, ``final``, ``library``, and ``private``. Any other annotation renders the class invalid. - -A valid class may not inherit from a final class, from itself, or from more than one primitive type. - -Class environments -~~~~~~~~~~~~~~~~~~ - -For each of modules, types, predicates, and fields a class *inherits*, *declares*, and *exports* an environment. These are defined as follows (with X denoting the type of entity we are currently considering): - -- The *inherited X environment* of a class is the union of the exported X environments of its base types. - -- The *declared X environment* of a class is the multimap of X declarations in the class itself. - -- The *exported X environment* of a class is the overriding union of its declared X environment (excluding ``private`` declaration entries) with its inherited X environment. - -- The *external X environment* of a class is the visible X environment of the enclosing module. - -- The *visible X environment* is the overriding union of the declared X environment and the inherited X environment; overriding unioned with the external X environment. - -The program is invalid if any of these environments is not definite. - -Members -~~~~~~~ - -Each member of a class is either a *character*, a predicate, or a field: - -:: - - member ::= character | predicate | field - character ::= annotations classname "(" ")" "{" formula "}" - field ::= annotations var_decl ";" - -Characters -^^^^^^^^^^ - -A valid character must have the same name as the name of the class. A valid class has at most one character provided in the source code. - -A valid character can be annotated with ``cached``. Any other annotation renders the character invalid. - -Member predicates -^^^^^^^^^^^^^^^^^ - -A predicate that is a member of a class is called a *member predicate*. The name of the predicate is the identifier just before the open parenthesis. - -A member predicate adds a mapping from the predicate name and arity to the predicate declaration in the class's declared predicate environment. - -A valid member predicate can be annotated with ``abstract``, ``cached``, ``final``, ``private``, ``deprecated``, and ``override``. - -If a type is provided before the name of the member predicate, then that type is the *result type* of the predicate. Otherwise, the predicate has no result type. The types of the variables in the ``var_decls`` are called the predicate's *argument types*. - -A member predicate ``p`` with enclosing class ``C`` *overrides* a member predicate ``p'`` with enclosing class ``D`` when ``C`` inherits from ``D``, ``p'`` is visible in ``C``, and both ``p`` and ``p'`` have the same name and the same arity. An overriding predicate must have the same sequence of argument types as any predicates which it overrides, otherwise the program is invalid. - -Member predicates have one or more *root definitions*. If a member predicate overrides no other member predicate, then it is its own root definition. Otherwise, its root definitions are those of any member predicate that it overrides. - -A valid member predicate must have a body unless it is abstract or external, in which case it must not have a body. - -A valid member predicate must override another member predicate if it is annotated override. - -When member predicate ``p`` overrides member predicate ``q``, either ``p`` and ``q`` must both have a result type, or neither of them may have a result type. If they do have result types, then the result type of ``p`` must be a subtype of the result type of ``q``. ``q`` may not be a final predicate. If ``p`` is abstract, then ``q`` must be as well. - -A class may not inherit from a class with an abstract member predicate unless it either includes a member predicate overriding that abstract predicate, or it inherits from another class that does. - -A valid class must include a non-private predicate named ``toString`` with no arguments and a result type of ``string``, or it must inherit from a class that does. - -A valid class may not inherit from two different classes that include a predicate with the same name and number of arguments, unless either one of the predicates overrides the other, or the class defines a predicate that overrides both of them. - -The typing environment for a member predicate or character is the same as if it were a non-member predicate, except that it additionally maps ``this`` to a type. If the member is a character, then the typing environment maps ``this`` to the class domain type of the class. Otherwise, it maps ``this`` to the class type of the class itself. - -Fields -^^^^^^ - -A field declaration introduces a mapping from the field name to the field declaration in the class's declared field environment. - -Select clauses -~~~~~~~~~~~~~~ - -A QL file may include at most one *select clause*. That select clause has the following syntax: - -:: - - select ::= ("from" var_decls)? ("where" formula)? "select" select_exprs ("order" "by" orderbys)? - -A valid QLL file may not include any select clauses. - -A select clause is considered to be a declaration of an anonymous predicate whose arguments correspond to the select expressions of the select clause. - -The ``from`` keyword, if present, is followed by the *variables* of the formula. Otherwise, the select clause has no variables. - -The ``where`` keyword, if present, is followed by the *formula* of the select clause. Otherwise, the select clause has no formula. - -The ``select`` keyword is followed by a number of *select expressions*. Select expressions have the following syntax: - -:: - - as_exprs ::= as_expr ("," as_expr)* - as_expr ::= expr ("as" simpleId)? - -The keyword ``as`` gives a *label* to the select expression it is part of. No two select expressions may have the same label. No expression label may be the same as one of the variables of the select clause. - -The ``order`` keyword, if present, is followed by a number of *ordering directives*. Ordering directives have the following syntax: - -:: - - orderbys ::= orderby ("," orderby)* - orderby ::= simpleId ("asc" | "desc")? - -Each identifier in an ordering directive must identify exactly one of the select expressions. It must either be the label of the expression, or it must be a variable expression that is equivalent to exactly one of the select expressions. The type of the designated select expression must be a subtype of a primitive type. - -No select expression may be specified by more than one ordering directive. See `Ordering <#ordering>`__ for more information. - -Queries -~~~~~~~ - -The queries in a QL module are: - -- The select clause, if any, defined in that module. -- Any predicates annotated with ``query`` which are in scope in that module. - -The target predicate of the query is either the select clause or the annotated predicate. - -Each argument of the target predicate of the query must be of a type which has a ``toString()`` member predicate. - -Expressions ------------ - -Expressions are a form of syntax used to denote values. Every expression has a typing environment that is determined by the context where the expression occurs. Every valid expression has a type, as specified in this section, except if it is a don't-care expression. - -Given a named tuple and a store, each expression has one or more *values*. This section specifies the values of each kind of expression. - -There are several kinds of expressions: - -:: - - exprs ::= expr ("," expr)* - - expr ::= dontcare - | unop - | binop - | cast - | primary - - primary ::= eparen - | literal - | variable - | super_expr - | callwithresult - | postfix_cast - | aggregation - | any - -Parenthesized expressions -~~~~~~~~~~~~~~~~~~~~~~~~~ - -A parenthesized expression is an expression surrounded by parentheses: - -:: - - eparen ::= "(" expr ")" - -The type environment of the nested expression is the same as that of the outer expression. The type and values of the outer expression are the same as those of the nested expression. - -Don't-care expressions -~~~~~~~~~~~~~~~~~~~~~~ - -A don't-care expression is written as a single underscore: - -:: - - dontcare ::= "_" - -All values are values of a don't-care expression. - -Literals -~~~~~~~~ - -A literal expression is as follows: - -:: - - literal ::= "false" | "true" | int | float | string - -The type of a literal expression is the type of the value denoted by the literal: ``boolean`` for ``false`` or ``true``, ``int`` for an integer literal, ``float`` for a floating-point literal, or ``string`` for a string literal. The value of a literal expression is the same as the value denoted by the literal. - -Unary operations -~~~~~~~~~~~~~~~~ - -A unary operation is the application of ``+`` or ``-`` to another expression: - -:: - - unop ::= "+" expr - | "-" expr - -The ``+`` or ``-`` in the operation is called the *operator*, and the expression is called the *operand*. The typing environment of the operand is the same as for the unary operation. - -For a valid unary operation, the operand must be of type ``int`` or ``float``. The operation has the same type as its operand. - -If the operator is ``+``, then the values of the expression are the same as the values of the operand. If the operator is ``-``, then the values of the expression are the arithmetic negations of the values of the operand. - -Binary operations -~~~~~~~~~~~~~~~~~ - -A binary operation is written as a *left operand* followed by a *binary operator*, followed by a *right operand*: - -:: - - binop ::= expr "+" expr - | expr "-" expr - | expr "*" expr - | expr "/" expr - | expr "%" expr - -The typing environment for the two environments is the same as for the operation. If the operator is ``+``, then either both operands must be subtypes of ``int`` or ``float``, or at least one operand must be a subtype of ``string``. If the operator is anything else, then each operand must be a subtype of ``int`` or ``float``. - -The type of the operation is ``string`` if either operand is a subtype of ``string``. Otherwise, the type of the operation is ``int`` if both operands are subtypes of ``int``. Otherwise, the type of the operation is ``float``. - -If the result is of type ``string``, then the *left values* of the operation are the values of a "call with results" expression with the left operand as the receiver, ``toString`` as the predicate name, and no arguments (see `Calls with results <#calls-with-results>`__). Otherwise the left values are the values of the left operand. Likewise, the *right values* are either the values from calling ``toString`` on the right operand, or the values of the right operand as it is. - -The binary operation has one value for each combination of a left value and a right value. That value is determined as follows: - -- If the left and right operand types are subtypes of string, then the operation has a value that is the concatenation of the left and right values. - -- Otherwise, if both operand types are subtypes of ``int``, then the value of the operation is the result of applying the two's-complement 32-bit integer operation corresponding to the QL binary operator. - -- Otherwise, both operand types must be subtypes of ``float``. If either operand is of type ``int`` then they are converted to a float. The value of the operation is then the result of applying the IEEE 754 floating-point operator that corresponds to the QL binary operator: addition for ``+``, subtraction for ``-``, multiplication for ``*``, division for ``/``, or remainder for ``%``. - -Variables -~~~~~~~~~ - -A variable has the following syntax: - -:: - - variable ::= varname | "this" | "result" - -A valid variable expression must occur in the typing environment. The type of the variable expression is the same as the type of the variable in the typing environment. - -The value of the variable is the value of the variable in the named tuple. - -Super -~~~~~ - -A super expression has the following syntax: - -:: - - super_expr ::= "super" | type "." "super" - -For a super expression to be valid, the ``this`` keyword must have a type and value in the typing environment. The type of the expression is the same as the type of ``this`` in the typing environment. - -A super expression may only occur in a QL program as the receiver expression for a predicate call. - -If a super expression includes a ``type``, then that type must be a class that the enclosing class inherits from. - -If the super expression does not include a type, then the enclosing class must have a single declared base type, and that base type must be a class. - -The value of a super expression is the same as the value of ``this`` in the named tuple. - -Casts -~~~~~ - -A cast expression is a type in parentheses followed by another expression: - -:: - - cast ::= "(" type ")" expr - -The typing environment for the nested expression is the same as for the cast expression. The type of the cast expression is the type between parentheses. - -The values of the cast expression are those values of the nested expression that are in the type given within parentheses. - -For casts between the primitive ``float`` and ``int`` types, the above rule means that for the cast expression to have a value, it must be representable as both 32-bit two's complement integers and 64-bit IEEE 754 floats. Other values will not be included in the values of the cast expression. - -Postfix casts -~~~~~~~~~~~~~ - -*Available from Semmle 1.9.4 onward.* A postfix cast is a primary expression followed by a dot and then a class or primitive type in parentheses: - -:: - - postfix_cast ::= primary "." "(" type ")" - -All the rules for ordinary casts apply to postfix casts: a postfix cast is exactly equivalent to a parenthesized ordinary cast. - -Calls with results -~~~~~~~~~~~~~~~~~~ - -An expression for a call with results is of one of two forms: - -:: - - callwithresult ::= predicateRef (closure)? "(" (exprs)? ")" - | primary "." predicateName (closure)? "(" (exprs)? ")" - closure ::= "*" | "+" - -The expressions in parentheses are the *arguments* of the call. The expression before the dot, if there is one, is the *receiver* of the call. - -The type environment for the arguments is the same as for the call. - -A valid call with results must *resolve* to exactly one predicate. The ways a call can resolve are as follows: - -- If the call has no receiver, then it can resolve to a non-member predicate. If the predicate name is a simple identifier, then the predicate is resolved by looking up its name and arity in the visible predicate environment of the enclosing class or module. - - If the predicate name is a selection identifier, then the qualifier is resolved as a module (see `Module resolution <#module-resolution>`__). The identifier is then resolved in the exported predicate environment of the qualifier module. - -- If the call has a super expression as the receiver, then it resolves to a member predicate in a class the enclosing class inherits from. If the super expression is unqualified, then the super-class is the single class that the current class inherits from. If there is not exactly one such class, then the program is invalid. Otherwise the super-class is the class named by the qualifier of the super expression. The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. If there is more than one such predicate, then the predicate call is not valid. - -For each argument other than a don't-care expression, the type of the argument must be compatible with the type of the corresponding argument type of the predicate, otherwise the call is invalid. - -A valid call with results must resolve to a predicate that has a result type. That result type is also the type of the call. - -If the resolved predicate is built in, then the call may not include a closure. If the call does have a closure, then it must resolve to a predicate where the *relational arity* of the predicate is 2. The relational arity of a predicate is the sum of the following numbers: - -- The number of arguments to the predicate. - -- The number 1 if the predicate is a member predicate, otherwise 0. - -- The number 1 if the predicate has a result, otherwise 0. - -If the call resolves to a member predicate, then the *receiver values* are as follows. If the call has a receiver, then the receiver values are the values of that receiver. If the call does not have a receiver, then the single receiver value is the value of ``this`` in the contextual named tuple. - -The *tuple prefixes* of a call with results include one value from each of the argument expressions' values, in the same order as the order of the arguments. If the call resolves to a non-member predicate, then those values are exactly the tuple prefixes of the call. If the call instead resolves to a member predicate, then the tuple prefixes additionally include a receiver value, ordered before the argument values. - -The *matching tuples* of a call with results are all ordered tuples that are one of the tuple prefixes followed by any value of the same type as the call. If the call has no closure, then all matching tuples must additionally satisfy the resolved predicate of the call, unless the receiver is a super expression, in which case they must *directly* satisfy the resolved predicate of the call. If the call has a ``*`` or ``+`` closure, then the matching tuples must satisfy or directly satisfy the associated closure of the resolved predicate. - -The values of a call with results are the final elements of each of the call's matching tuples. - -Aggregations -~~~~~~~~~~~~ - -An aggregation can be written in one of two forms: - -:: - - aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" - | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" - | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" - - aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" - - aggorderbys ::= aggorderby ("," aggorderby)* - - aggorderby ::= expr ("asc" | "desc")? - -The expression enclosed in square brackets (``[`` and ``]``, U+005B and U+005D), if present, is called the *rank expression*. It must have type ``int`` in the enclosing environment. - -The ``as_exprs``, if present, are called the *aggregation expressions*. If an aggregation expression is of the form ``expr as v`` then the expression is said to be *named* v. - -The rank expression must be present if the aggregate id is ``rank``; otherwise it must not be present. - -Apart from the presence or absence of the rank variable, all other reduced forms of an aggregation are equivalent to a full form using the following steps: - -- If the formula is omitted, then it is taken to be ``any()``. -- If there are no aggregation expressions, then either: - - - The aggregation id is ``count`` or ``strictcount`` and the expression is taken to be ``1``. - - There must be precisely one variable declaration, and the aggregation expression is taken to be a reference to that variable. - -- If the aggregation id is ``concat`` or ``strictconcat`` and it has a single expression then the second expression is taken to be ``""``. -- If the ``monotonicAggregates`` language pragma is not enabled, or the original formula and variable declarations are both omitted, then the aggregate is transformed as follows: - - - For each aggregation expression ``expr_i``, a fresh variable ``v_i`` is declared with the same type as the expression in addition to the original variable declarations. - - The new range is the conjunction of the original range and a term ``v_i = expr_i`` for each aggregation expression ``expr_i``. - - Each original aggregation expression ``expr_i`` is replaced by a new aggregation expression ``v_i``. - -The variables in the variable declarations list must not occur in the typing environment. - -The typing environment for the rank expression is the same as for the aggregation. - -The typing environment for the formula is obtained by taking the typing environment for the aggregation and adding all the variable types in the given ``var_decls`` list. - -The typing environment for an aggregation expression is obtained by taking the typing environment for the formula and then, for each named aggregation expression that occurs earlier than the current expression, adding a mapping from the earlier expression's name to the earlier expression's type. - -The typing environment for ordering directives is obtained by taking the typing environment for the formula and then, for each named aggregation expression in the aggregation, adding a mapping from the expression's name to the expression's type. - -The number and types of the aggregation expressions are restricted as follows: - -- A ``max``, ``min``, ``rank`` or ``unique`` aggregation must have a single expression. -- The type of the expression in a ``max``, ``min`` or ``rank`` aggregation without an ordering directive expression must be an orderable type. -- A ``count`` or ``strictcount`` aggregation must not have an expression. -- A ``sum``, ``strictsum`` or ``avg`` aggregation must have a single aggregation expression, which must have a type which is a subtype of ``float``. -- A ``concat`` or ``strictconcat`` aggregation must have two expressions. Both expressions must have types which are subtypes of ``string``. - -The type of a ``count``, ``strictcount`` aggregation is ``int``. The type of an ``avg`` aggregation is ``float``. The type of a ``concat`` or ``strictconcat`` aggregation is ``string``. The type of a ``sum`` or ``strictsum`` aggregation is ``int`` if the aggregation expression is a subtype of ``int``, otherwise it is ``float``. The type of a ``rank``, ``min`` or ``max`` aggregation is the type of the single expression. - -An ordering directive may only be specified for a ``max``, ``min``, ``rank``, ``concat`` or ``strictconcat`` aggregation. The type of the expression in an ordering directive must be an orderable type. - -The values of the aggregation expression are determined as follows. Firstly, the *range tuples* are extensions of the named tuple that the aggregation is being evaluated in with the variable declarations of the aggregation, and which *match* the formula (see `Formulas <#formulas>`__). - -For each range tuple, the *aggregation tuples* are the extension of the range tuples to *aggregation variables* and *sort variables*. - -The aggregation variables are given by the aggregation expressions. If an aggregation expression is named, then its aggregation variable is given by its name, otherwise a fresh synthetic variable is created. The value is given by evaluating the expression with the named tuple being the result of the previous expression, or the range tuple if this is the first aggregation expression. - -The sort variables are synthetic variables created for each expression in the ordering directive with values given by the values of the expressions within the ordering directive. - -If the aggregation id is ``max``, ``min`` or ``rank`` and there was no ordering directive, then for each aggregation tuple a synthetic sort variable is added with value given by the aggregation variable. - -The values of the aggregation expression are given by applying the aggregation function to each set of tuples obtained by picking exactly one aggregation tuple for each range tuple. - -- If the aggregation id is ``avg``, and the set is non-empty, then the resulting value is the average of the value for the aggregation variable in each tuple in the set, weighted by the number of tuples in the set, after converting the value to a floating-point number. - -- If the aggregation id is ``count``, then the resulting value is the number of tuples in the set. If there are no tuples in the set, then the value is the integer ``0``. - -- If the aggregation id is ``max``, then the values are the those values of the aggregation variable which are associated with a maximal tuple of sort values. If the set is empty, then the aggregation has no value. - -- If the aggregation id is ``min``, then the values are the those values of the aggregation variable which are associated with a minimal tuple of sort values. If the set is empty, then the aggregation has no value. - -- If the aggregation id is ``rank``, then the resulting values are values of the aggregation variable such that the number of aggregation tuples with a strictly smaller tuple of sort variables is exactly one less than an integer bound by the rank expression of the aggregation. If no such values exist, then the aggregation has no values. - -- If the aggregation id is ``strictcount``, then the resulting value is the same as if the aggregation id were ``count``, unless the set of tuples is empty. If the set of tuples is empty, then the aggregation has no value. - -- If the aggregation id is ``strictsum``, then the resulting value is the same as if the aggregation id were ``sum``, unless the set of tuples is empty. If the set of tuples is empty, then the aggregation has no value. - -- If the aggregation id is ``sum``, then the resulting value is the same as the sum of the values of the aggregation variable across the tuples in the set, weighted by the number of times each value occurs in the tuples in the set. If there are no tuples in the set, then the resulting value of the aggregation is the integer ``0``. - -- If the aggregation id is ``concat``, then there is one value for each value of the second aggregation variable, given by the concatenation of the value of the first aggregation variable of each tuple with the value of the second aggregation variable used as a separator, ordered by the sort variables. If there are multiple aggregation tuples with the same sort variables then the first distinguished value is used to break ties. If there are no tuples in the set, then the single value of the aggregation is the empty string. - -- If the aggregation id is ``strictconcat``, then the result is the same as for ``concat`` except in the case where there are no aggregation tuples in which case the aggregation has no value. - - - If the aggregation id is ``unique``, then the result is the value of the aggregation variable if there is precisely one such value. Otherwise, the aggregation has no value. - -Any -~~~ - -The ``any`` expression is a special kind of quantified expression. - -:: - - any ::= "any" "(" var_decls ("|" (formula)? ("|" expr)?)? ")" - -The values of an ``any`` expression are those values of the expression for which the formula matches. - -The abbreviated cases for an ``any`` expression are interpreted in the same way as for an aggregation. - -Ranges -~~~~~~ - -Range expressions denote a range of values. - -:: - - range ::= "[" expr ".." expr "]" - -Both expressions must be subtypes of ``int``, ``float``, or ``date``. If either of them are type ``date``, then both of them must be. - -If both expressions are subtypes of ``int`` then the type of the range is ``int``. If both expressions are subtypes of ``date`` then the type of the range is ``date``. Otherwise the type of the range is ``float``. - -The values of a range expression are those values which are ordered inclusively between a value of the first expression and a value of the second expression. - -Set literals -~~~~~~~~~~~~ - -Set literals denote a choice from a collection of values. - -:: - - setliteral ::= "[" expr ("," expr)* "]" - -Set literals can be of any type, but the types within a set literal have to be consistent according to the following criterion: At least one of the set elements has to be of a type that is a supertype of all the set element types. This supertype is the type of the set literal. For example, ``float`` is a supertype of ``float`` and ``int``, therefore ``x = [4, 5.6]`` is valid. On the other hand, ``y = [5, "test"]`` does not adhere to the criterion. - -The values of a set literal expression are all the values of all the contained element expressions. - -Set literals are supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise. - -Disambiguation of expressions ------------------------------ - -The grammar given in this section is disambiguated first by precedence, and second by associating left to right. The order of precedence from highest to lowest is: - -- casts -- unary ``+`` and ``-`` -- binary ``*`` , ``/`` and ``%`` -- binary ``+`` and ``-`` - -Additionally, whenever a sequence of tokens can be interpreted either as a call to a predicate with result (with specified closure), or as a binary operation with operator ``+`` or ``*``, the syntax is interpreted as a call to a predicate with result. - -Formulas --------- - -A formula is a form of syntax used to *match* a named tuple given a store. - -There are several kinds of formulas: - -:: - - formula ::= fparen - | disjunction - | conjunction - | implies - | ifthen - | negated - | quantified - | comparison - | instanceof - | inrange - | call - -This section specifies the syntax for each kind of formula and what tuples they match. - -Parenthesized formulas -~~~~~~~~~~~~~~~~~~~~~~ - -A parenthesized formula is a formula enclosed by a pair of parentheses: - -:: - - fparen ::= "(" formula ")" - -A parenthesized formula matches the same tuples as the nested formula matches. - -Disjunctions -~~~~~~~~~~~~ - -A disjunction is two formulas separated by the ``or`` keyword: - -:: - - disjunction ::= formula "or" formula - -A disjunction matches any tuple that matches either of the nested formulas. - -Conjunctions -~~~~~~~~~~~~ - -A conjunction is two formulas separated by the ``and`` keyword: - -:: - - conjunction ::= formula "and" formula - -A conjunction matches any tuple that also matches both of the two nested formulas. - -Implications -~~~~~~~~~~~~ - -An implication formula is two formulas separated by the ``implies`` keyword: - -:: - - implies ::= formula "implies" formula - -Neither of the two formulas may be another implication. - -An implied formula matches if either the second formula matches, or the first formula does not match. - -Conditional formulas -~~~~~~~~~~~~~~~~~~~~ - -A conditional formula has the following syntax: - -:: - - ifthen ::= "if" formula "then" formula "else" formula - -The first formula is called the *condition* of the conditional formula. The second formula is called the *true branch*, and the second formula is called the *false branch*. - -The conditional formula matches if the condition and the true branch both match. It also matches if the false branch matches and the condition does not match. - -Negations -~~~~~~~~~ - -A negation formula is a formula preceded by the ``not`` keyword: - -:: - - negated ::= "not" formula - -A negation formula matches any tuple that does not match the nested formula. - -Quantified formulas -~~~~~~~~~~~~~~~~~~~ - -A quantified formula has several syntaxes: - -:: - - quantified ::= "exists" "(" expr ")" - | "exists" "(" var_decls ("|" formula)? ("|" formula)? ")" - | "forall" "(" var_decls ("|" formula)? "|" formula ")" - | "forex" "(" var_decls ("|" formula)? "|" formula ")" - -In all cases, the typing environment for the nested expressions or formulas is the same as the typing environment for the quantified formula, except that it also maps the variables in the variable declaration to their associated types. - -The first form matches if the given expression has at least one value. - -For the other forms, the extensions of the current named tuple for the given variable declarations are called the *quantifier extensions*. The nested formulas are called the *first quantified formula* and, if present, the *second quantified formula*. - -The second ``exists`` formula matches if one of the quantifier extensions is such that the quantified formula or formulas all match. - -A ``forall`` formula that has one quantified formula matches if that quantified formula matches all of the quantifier extensions. A ``forall`` with two quantified formulas matches if the second formula matches all extensions where the first formula matches. - -A ``forex`` formula with one quantified formula matches under the same conditions as a ``forall`` formula matching, except that there must be at least one quantifier extension where that first quantified formula matches. - -Comparisons -~~~~~~~~~~~ - -A comparison formula is two expressions separated by a comparison operator: - -:: - - comparison ::= expr compop expr - compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" - -A comparison formula matches if there is one value of the left expression that is in the given ordering with one of the values of the right expression. The ordering used is specified in `Ordering <#ordering>`__. If one of the values is an integer and the other is a float value, then the integer is converted to a float value before the comparison. - -If the operator is ``=``, then at least one of the left and right expressions must have a type; if they both have a type, those types must be compatible. - -If the operator is ``!=``, then both expressions must have a type, and those types must be compatible. - -If the operator is any other operator, then both expressions must have a type. Those types must be compatible with each other. Each of those types must be orderable. - -Type checks -~~~~~~~~~~~ - -A type check formula has the following syntax: - -:: - - instanceof ::= expr "instanceof" type - -The type to the right of ``instanceof`` is called the *type-check type*. - -The type of the expression must be compatible with the type-check type. - -The formula matches if one of the values of the expression is in the type-check type. - -Range checks -~~~~~~~~~~~~ - -A range check has the following syntax: - -:: - - inrange ::= expr "in" range - -The formula is equivalent to ``expr "=" range``. - -Calls -~~~~~ - -A call has the following syntax: - -:: - - call ::= predicateRef (closure)? "(" (exprs)? ")" - | primary "." predicateName (closure)? "(" (exprs)? ")" - -The identifier is called the *predicate name* of the call. - -A call must resolve to a predicate, using the same definition of resolve as for calls with results (see `Calls with results <#calls-with-results>`__). - -The resolved predicate must not have a result type. - -If the resolved predicate is a built-in member predicate of a primitive type, then the call may not include a closure. If the call does have a closure, then the call must resolve to a predicate with relational arity of 2. - -The *candidate tuples* of a call are the ordered tuples formed by selecting a value from each of the arguments of the call. - -If the call has no closure, then it matches whenever one of the candidate tuples satisfies the resolved predicate of the call, unless the call has a super expression as a receiver, in which case the candidate tuple must *directly* satisfy the resolved predicate. If the call has ``*`` or ``+`` closure, then the call matches whenever one of the candidate tuples satisfies or directly satisfies the associated closure of the resolved predicate. - -Disambiguation of formulas -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The grammar given in this section is disambiguated first by precedence, and second by associating left to right, except for implication which is non-associative. The order of precedence from highest to lowest is: - -- Negation - -- Conditional formulas - -- Conjunction - -- Disjunction - -- Implication - -Aliases -------- - -Aliases define new names for existing QL entities. - -:: - - alias ::= annotations "predicate" literalId "=" predicateRef "/" int ";" - | annotations "class" classname "=" type ";" - | annotations "module" modulename "=" moduleId ";" - - -An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively. - -Built-ins ---------- - -A QL database includes a number of *built-in predicates* . This section defines a number of built-in predicates that all databases include. Each database also includes a number of additional non-member predicates that are not specified in this document. - -This section gives several tables of built-in predicates. For each predicate, the table gives the result type of each predicate that has one, and the sequence of argument types. - -Each table also specifies which ordered tuples are in the database content of each predicate. It specifies this with a description that holds true for exactly the tuples that are included. In each description, the "result" is the last element of each tuple, if the predicate has a result type. The "receiver" is the first element of each tuple. The "arguments" are all elements of each tuple other than the result and the receiver. - -Non-member built-ins -~~~~~~~~~~~~~~~~~~~~ - -The following built-in predicates are non-member predicates: - -+-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Name | Result type | Argument types | Content | -+===========+=============+====================================+============================================================================================================================================================================================================+ -| ``any`` | | | The empty tuple. | -+-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``none`` | | | No tuples. | -+-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``toUrl`` | | string, int, int, int, int, string | Let the arguments be ``file``, ``startLine``, ``startCol``, ``endLine``, ``endCol``, and ``url``. The predicate holds if ``url`` is equal to the string ``file://file:startLine:startCol:endLine:endCol``. | -+-----------+-------------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -Built-ins for boolean -~~~~~~~~~~~~~~~~~~~~~ - -The following built-in predicates are members of type ``boolean``: - -+----------------+-------------+----------------+--------------------------------------------------------------------------+ -| Name | Result type | Argument types | Content | -+================+=============+================+==========================================================================+ -| ``booleanAnd`` | boolean | boolean | The result is the boolean and of the receiver and the argument. | -+----------------+-------------+----------------+--------------------------------------------------------------------------+ -| ``booleanNot`` | boolean | | The result is the boolean not of the receiver. | -+----------------+-------------+----------------+--------------------------------------------------------------------------+ -| ``booleanOr`` | boolean | boolean | The result is the boolean or of the receiver and the argument. | -+----------------+-------------+----------------+--------------------------------------------------------------------------+ -| ``booleanXor`` | boolean | boolean | The result is the boolean exclusive or of the receiver and the argument. | -+----------------+-------------+----------------+--------------------------------------------------------------------------+ -| ``toString`` | string | | The result is "true" if the receiver is ``true``, otherwise "false." | -+----------------+-------------+----------------+--------------------------------------------------------------------------+ - -Built-ins for date -~~~~~~~~~~~~~~~~~~ - -The following built-in predicates are members of type ``date``: - -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| Name | Result type | Argument types | Content | -+================+=============+================+================================================================================================+ -| ``daysTo`` | int | date | The result is the number of days between but not including the receiver and the argument. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``getDay`` | int | | The result is the day component of the receiver. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``getHours`` | int | | The result is the hours component of the receiver. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``getMinutes`` | int | | The result is the minutes component of the receiver. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``getMonth`` | string | | The result is a string that is determined by the month component of the receiver. | -| | | | The string is one of ``January``, ``February``, ``March``, ``April``, ``May``, ``June``, | -| | | | ``July``, ``August``, ``September``, ``October``, ``November``, or ``December``. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``getSeconds`` | int | | The result is the seconds component of the receiver. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``getYear`` | int | | The result is the year component of the receiver. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``toISO`` | string | | The result is a string representation of the date. The representation is left unspecified. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ -| ``toString`` | string | | The result is a string representation of the date. The representation is left unspecified. | -+----------------+-------------+----------------+------------------------------------------------------------------------------------------------+ - -Built-ins for float -~~~~~~~~~~~~~~~~~~~ - -The following built-in predicates are members of type ``float``: - -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| Name | Result type | Argument types | Content | -+===============+=============+================+===========================================================================================================================+ -| ``abs`` | float | | The result is the absolute value of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``acos`` | float | | The result is the inverse cosine of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``asin`` | float | | The result is the inverse sine of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``atan`` | float | | The result is the inverse tangent of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``ceil`` | int | | The result is the smallest integer greater than or equal to the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``copySign`` | float | float | The result is the floating point number with the magnitude of the receiver and the sign of the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``cos`` | float | | The result is the cosine of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``cosh`` | float | | The result is the hyperbolic cosine of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``exp`` | float | | The result is the value of e, the base of the natural logarithm, raised to the power of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``floor`` | int | | The result is the largest integer that is not greater than the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``log`` | float | | The result is the natural logarithm of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``log`` | float | float | The result is the logarithm of the receiver with the base of the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``log`` | float | int | The result is the logarithm of the receiver with the base of the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``log10`` | float | | The result is the base-10 logarithm of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``log2`` | float | | The result is the base-2 logarithm of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``maximum`` | float | float | The result is the larger of the receiver and the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``maximum`` | float | int | The result is the larger of the receiver and the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``minimum`` | float | float | The result is the smaller of the receiver and the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``minimum`` | float | int | The result is the smaller of the receiver and the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``nextAfter`` | float | float | The result is the number adjacent to the receiver in the direction of the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``nextDown`` | float | | The result is the number adjacent to the receiver in the direction of negative infinity. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``nextUp`` | float | | The result is the number adjacent to the receiver in the direction of positive infinity. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``pow`` | float | float | The result is the receiver raised to the power of the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``pow`` | float | int | The result is the receiver raised to the power of the argument. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``signum`` | float | | The result is the sign of the receiver: zero if it is zero, 1.0 if it is greater than zero, -1.0 if it is less than zero. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``sin`` | float | | The result is the sine of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``sinh`` | float | | The result is the hyperbolic sine of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``sqrt`` | float | | The result is the square root of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``tan`` | float | | The result is the tangent of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``tanh`` | float | | The result is the hyperbolic tangent of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``toString`` | string | | The decimal representation of the number as a string. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ -| ``ulp`` | float | | The result is the ULP (unit in last place) of the receiver. | -+---------------+-------------+----------------+---------------------------------------------------------------------------------------------------------------------------+ - -Built-ins for int -~~~~~~~~~~~~~~~~~ - -The following built-in predicates are members of type ``int``: - -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| Name | Result type | Argument types | Content | -+=========================+=============+================+================================================================================================================+ -| ``abs`` | int | | The result is the absolute value of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``acos`` | float | | The result is the inverse cosine of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``asin`` | float | | The result is the inverse sine of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``atan`` | float | | The result is the inverse tangent of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``cos`` | float | | The result is the cosine of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``cosh`` | float | | The result is the hyperbolic cosine of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``exp`` | float | | The result is the value of value of e, the base of the natural logarithm, raised to the power of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``gcd`` | int | int | The result is the greatest common divisor of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``log`` | float | | The result is the natural logarithm of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``log`` | float | float | The result is the logarithm of the receiver with the base of the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``log`` | float | int | The result is the logarithm of the receiver with the base of the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``log10`` | float | | The result is the base-10 logarithm of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``log2`` | float | | The result is the base-2 logarithm of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``maximum`` | float | float | The result is the larger of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``maximum`` | int | int | The result is the larger of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``minimum`` | float | float | The result is the smaller of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``minimum`` | int | int | The result is the smaller of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``pow`` | float | float | The result is the receiver raised to the power of the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``pow`` | float | int | The result is the receiver raised to the power of the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``sin`` | float | | The result is the sine of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``sinh`` | float | | The result is the hyperbolic sine of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``sqrt`` | float | | The result is the square root of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``tan`` | float | | The result is the tangent of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``tanh`` | float | | The result is the hyperbolic tangent of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``bitAnd`` | int | int | The result is the bitwise and of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``bitOr`` | int | int | The result is the bitwise or of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``bitXor`` | int | int | The result is the bitwise xor of the receiver and the argument. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``bitNot`` | int | | The result is the bitwise complement of the receiver. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``bitShiftLeft`` | int | int | The result is the bitwise left shift of the receiver by the argument, modulo 32. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``bitShiftRight`` | int | int | The result is the bitwise right shift of the receiver by the argument, modulo 32. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``bitShiftRightSigned`` | int | int | The result is the signed bitwise right shift of the receiver by the argument, modulo 32. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ -| ``toString`` | string | | The result is the decimal representation of the number as a string. | -+-------------------------+-------------+----------------+----------------------------------------------------------------------------------------------------------------+ - -The leftmost bit after ``bitShiftRightSigned`` depends on sign extension, whereas after ``bitShiftRight`` it is zero. - -Built-ins for string -~~~~~~~~~~~~~~~~~~~~ - -The following built-in predicates are members of type ``string``: - -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Name | Result type | Argument types | Content | -+======================+=============+==================+========================================================================================================================================================================================================================================================================================================================================================================================+ -| ``charAt`` | string | int | The result is a 1-character string containing the character in the receiver at the index given by the argument. The first element of the string is at index 0. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``indexOf`` | int | string | The result is an index into the receiver where the argument occurs. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``indexOf`` | int | string, int, int | Let the arguments be ``s``, ``n``, and ``start``. The result is the index of occurrence ``n`` of ``substring`` ``s`` in the receiver that is no earlier in the string than ``start``. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``isLowercase`` | | | The receiver contains no upper-case letters. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``isUppercase`` | | | The receiver contains no lower-case letters. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``length`` | int | | The result is the number of characters in the receiver. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``matches`` | | string | The argument is a pattern that matches the receiver, in the same way as the LIKE operator in SQL. Patterns may include ``_`` to match a single character and ``%`` to match any sequence of characters. A backslash can be used to escape an underscore, a percent, or a backslash. Otherwise, all characters in the pattern other than ``_`` and ``%`` and ``\\`` must match exactly. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``prefix`` | string | int | The result is the prefix of the receiver that has a length exactly equal to the argument. If the argument is negative or greater than the receiver's length, then there is no result. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``regexpCapture`` | string | string, int | The receiver exactly matches the regex in the first argument, and the result is the group of the match numbered by the second argument. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``regexpFind`` | string | string, int, int | The receiver contains one or more occurrences of the regex in the first argument. The result is the ``substring`` which matches the regex, the second argument is the occurrence number, and the third argument is the index within the receiver at which the occurrence begins. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``regexpMatch`` | | string | The receiver matches the argument as a regex. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``regexpReplaceAll`` | string | string, string | The result is obtained by replacing all occurrences in the receiver of the first argument as a regex by the second argument. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``replaceAll`` | string | string, string | The result is obtained by replacing all occurrences in the receiver of the first argument by the second. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``splitAt`` | string | string | The result is one of the strings obtained by splitting the receiver at every occurrence of the argument. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``splitAt`` | string | string, int | Let the arguments be ``delim`` and ``i``. The result is field number ``i`` of the fields obtained by splitting the receiver at every occurrence of ``delim``. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``substring`` | string | int, int | The result is the ``substring`` of the receiver starting at the index of the first argument and ending just before the index of the second argument. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``suffix`` | string | int | The result is the suffix of the receiver that has a length exactly equal to the receiver's length minus the argument. If the argument is negative or greater than the receiver's length, then there is no result. As a result, the identity ``s.prefix(i)+s.suffix(i)=s`` holds for ``i`` in ``[0, s.length()]``. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``toDate`` | date | | The result is a date value determined by the receiver. The format of the receiver is unspecified, except that if ``(d, s)`` is in ``date.toString``, ``(s, d)`` is in ``string.toDate``. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``toFloat`` | float | | The result is the float whose value is represented by the receiver. If the receiver cannot be parsed as a float then there is no result. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``toInt`` | int | | The result is the integer whose value is represented by the receiver. If the receiver cannot be parsed as an integer or cannot be represented as a QL ``int``, then there is no result. The parser accepts an optional leading ``-`` or ``+`` character, followed by one or more decimal digits. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``toLowerCase`` | string | | The result is the receiver with all letters converted to lower case. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``toString`` | string | | The result is the receiver. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``toUpperCase`` | string | | The result is the receiver with all letters converted to upper case. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``trim`` | string | | The result is the receiver with all whitespace removed from the beginning and end of the string. | -+----------------------+-------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -Regular expressions are as defined by ``java.util.Pattern`` in Java. - -Evaluation ----------- - -This section specifies the evaluation of a QL program. Evaluation happens in three phases. First, the program is stratified into a number of layers. Second, the layers are evaluated one by one. Finally, the queries in the QL file are evaluated to produce sets of ordered tuples. - -Stratification -~~~~~~~~~~~~~~ - -A QL program can be *stratified* to a sequence of *layers*. A layer is a set of predicates and types. - -A valid stratification must include each predicate and type in the QL program. It must not include any other predicates or types. - -A valid stratification must not include the same predicate in multiple layers. - -Formulas, variable declarations and expressions within a predicate body have a *negation polarity* that is positive, negative, or zero. Positive and negative are opposites of each other, while zero is the opposite of itself. The negation polarity of a formula or expression is then determined as follows: - -- The body of a predicate is positive. - -- The formula within a negation formula has the opposite polarity to that of the negation formula. - -- The condition of a conditional formula has zero polarity. - -- The formula on the left of an implication formula has the opposite polarity to that of the implication. - -- The formula and variable declarations of an aggregate have zero polarity. - -- If the ``monotonicAggregates`` language pragma is not enabled, or the original formula and variable declarations are both omitted, then the expressions and order by expressions of the aggregate have zero polarity. - -- If the ``monotonicAggregates`` language pragma is enabled, and the original formula and variable declarations were not both omitted, then the expressions and order by expressions of the aggregate have the polarity of the aggregate. - -- If a ``forall`` has two quantified formulas, then the first quantified formula has the opposite polarity to that of the ``forall``. - -- The variable declarations of a ``forall`` have the opposite polarity to that of the ``forall``. - -- If a ``forex`` has two quantified formulas, then the first quantified formula has zero polarity. - -- The variable declarations of a ``forex`` have zero polarity. - -- In all other cases, a formula or expression has the same polarity as its immediately enclosing formula or expression. - -For a member predicate ``p`` we define the *strict dispatch dependencies*. The strict dispatch dependencies are defined as: - -- The strict dispatch dependencies of any predicates that override ``p``. -- If ``p`` is not abstract, ``C.class`` for any class ``C`` with a predicate that overrides ``p``. - -For a member predicate ``p`` we define the *dispatch dependencies*. The dispatch dependencies are defined as: - -- The dispatch dependencies of predicates that override ``p``. -- The predicate ``p`` itself. -- ``C.class`` where ``C`` is the class that defines ``p``. - -Predicates, and types can *depend* and *strictly depend* on each other. Such dependencies exist in the following circumstances: - -- If ``A`` strictly depends on ``B``, then ``A`` depends on ``B``. - -- If ``A`` depends on ``B``, then ``A`` also depends on anything on which ``B`` depends. - -- If ``A`` strictly depends on ``B``, then ``A`` and anything depending on ``A`` strictly depend on anything on which ``B`` depends (including ``B`` itself). - -- If a predicate has a parameter whose declared type is a class type ``C``, it depends on ``C.class``. - -- If a predicate declares a result type which is a class type ``C``, it depends on ``C.class``. - -- A member predicate of class ``C`` depends on ``C.class``. - -- If a predicate contains a variable declaration of a variable whose declared type is a class type ``C``, then the predicate depends on ``C.class``. If the declaration has negative or zero polarity then the dependency is strict. - -- If a predicate contains a variable declaration with negative or zero polarity of a variable whose declared type is a class type ``C``, then the predicate strictly depends on ``C.class``. - -- If a predicate contains an expression whose type is a class type ``C``, then the predicate depends on ``C.class``. If the expression has negative or zero polarity then the dependency is strict. - -- A predicate containing a predicate call depends on the predicate to which the call resolves. If the call has negative or zero polarity then the dependency is strict. - -- A predicate containing a predicate call, which resolves to a member predicate and does not have a ``super`` expression as a qualifier, depends on the dispatch dependencies of the root definitions of the target of the call. If the call has negative or zero polarity then the dependencies are strict. The predicate strictly depends on the strict dispatch dependencies of the root definitions. - -- For each class ``C`` in the program, for each base class ``B`` of ``C``, ``C.extends`` depends on ``B.B``. - -- For each class ``C`` in the program, for each base type ``B`` of ``C`` that is not a class type, ``C.extends`` depends on ``B``. - -- For each class ``C`` in the program, ``C.class`` depends on ``C.C``. - -- For each class ``C`` in the program, ``C.C`` depends on ``C.extends``. - -- For each class ``C`` in the program that declares a field of class type ``B``, ``C.C`` depends on ``B.class``. - -- For each class ``C`` with a characteristic predicate, ``C.C`` depends on the characteristic predicate. - -- For each abstract class ``A`` in the program, for each type ``C`` that has ``A`` as a base type, ``A.class`` depends on ``C.class``. - -- A predicate with a higher-order body may strictly depend or depend on each predicate reference within the body. The exact dependencies are left unspecified. - -A valid stratification must have no predicate that depends on a predicate in a later layer. Additionally, it must have no predicate that strictly depends on a predicate in the same layer. - -If a QL program has no valid stratification, then the program itself is not valid. If it does have a stratification, a QL implementation must choose exactly one stratification. The precise stratification chosen is left unspecified. - -Layer evaluation -~~~~~~~~~~~~~~~~ - -The store is first initialized with the *database content* of all built-in predicates and external predicates. The database content of a predicate is a set of ordered tuples that are included in the database. - -Each layer of the stratification is *populated* in order. To populate a layer, each predicate in the layer is repeatedly populated until the store stops changing. The way that a predicate is populated is as follows: - -- To populate a predicate that has a formula as a body, find all named tuples with the variables of the predicate's arguments that match the body formula and the types of the variables. If the predicate has a result, then the matching named tuples should additionally have a value for ``result`` that is in the result type of the predicate. If the predicate is a member predicate, then the tuples should additionally have a value for ``this`` that is of the type assigned to ``this`` by the typing environment. For each such tuple, convert the named tuple to an ordered tuple by sequencing the values of the tuple, starting with ``this`` if present, followed by the predicate's arguments, followed by ``result`` if present. Add each such converted tuple to the predicate in the store. - -- To populate an abstract predicate, do nothing. - -- The population of predicates with a higher-order body is left only partially specified. A number of tuples are added to the given predicate in the store. The tuples that are added must be fully determined by the QL program and by the state of the store. - -- To populate the type ``C.extends`` for a class ``C``, identify each value ``v`` that has the following properties: It is in all non-class base types of ``C``, and for each class base type ``B`` of ``C`` it is in ``B.B``. For each such ``v``, add ``(v)`` to ``C.extends``. - -- To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. Otherwise add each tuple in ``C.extends`` into the store. - -- To populate the type ``C.class`` for a non-abstract class type ``C``, add each tuple in ``C.C`` to ``C.class``. - -- To populate the type ``C.class`` for an abstract class type ``C``, for each class ``D`` that has ``C`` as a base type add all tuples in ``D.class`` to ``C.class``. - -- To populate a select clause, find all named tuples with the variables declared in the ``from`` clause that match the formula given in the ``where`` clause, if there is one. For each named tuple, convert it to a set of ordered tuples where each element of the ordered tuple is, in the context of the named tuple, a value of one of the corresponding select expressions. Collect all ordered tuples that can be produced from all of the restricted named tuples in this way. Add each such converted tuple to the select clause in the store. - -Query evaluation -~~~~~~~~~~~~~~~~ - -A query is evaluated as follows: - -#. Identify all named tuples in the predicate targeted by the query. -#. Sequence the ordered tuples lexicographically. The first elements of the lexicographic order are the tuple elements specified by the ordering directives of the predicate targeted by the query, if it has any. Each such element is ordered either ascending (``asc``) or descending (``desc``) as specified by the ordering directive, or ascending if the ordering directive does not specify. This lexicographic order is only a partial order, if there are fewer ordering directives than elements of the tuples. An implementation may produce any sequence of the ordered tuples that satisfies this partial order. - -Summary of syntax ------------------ - -The complete grammar for QL is as follows: - -:: - - ql ::= moduleBody - - module ::= annotation* "module" modulename "{" moduleBody "}" - - moduleBody ::= (import | predicate | class | module | alias | select)* - - import ::= annotations "import" importModuleId ("as" modulename)? - - qualId ::= simpleId | qualId "." simpleId - - importModuleId ::= qualId - | importModuleId "::" simpleId - - select ::= ("from" var_decls)? ("where" formula)? "select" as_exprs ("order" "by" orderbys)? - - as_exprs ::= as_expr ("," as_expr)* - - as_expr ::= expr ("as" simpleId)? - - orderbys ::= orderby ("," orderby)* - - orderby ::= simpleId ("asc" | "desc")? - - predicate ::= annotations head optbody - - annotations ::= annotation* - - annotation ::= simpleAnnotation | argsAnnotation - - simpleAnnotation ::= "abstract" - | "cached" - | "external" - | "final" - | "transient" - | "library" - | "private" - | "deprecated" - | "override" - | "query" - - argsAnnotation ::= "pragma" "[" ("noinline" | "nomagic" | "noopt") "]" - | "language" "[" "monotonicAggregates" "]" - | "bindingset" "[" (variable ( "," variable)*)? "]" - - head ::= ("predicate" | type) predicateName "(" (var_decls)? ")" - - optbody ::= ";" - | "{" formula "}" - | "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")" - - class ::= annotations "class" classname "extends" type ("," type)* "{" member* "}" - - member ::= character | predicate | field - - character ::= annotations classname "(" ")" "{" formula "}" - - field ::= annotations var_decl ";" - - moduleId ::= simpleId | moduleId "::" simpleId - - type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string" - - exprs ::= expr ("," expr)* - - alias := annotations "predicate" literalId "=" predicateRef "/" int ";" - | annotations "class" classname "=" type ";" - | annotations "module" modulename "=" moduleId ";" - - var_decls ::= var_decl ("," var_decl)* - - var_decl ::= type simpleId - - formula ::= fparen - | disjunction - | conjunction - | implies - | ifthen - | negated - | quantified - | comparison - | instanceof - | inrange - | call - - fparen ::= "(" formula ")" - - disjunction ::= formula "or" formula - - conjunction ::= formula "and" formula - - implies ::= formula "implies" formula - - ifthen ::= "if" formula "then" formula "else" formula - - negated ::= "not" formula - - quantified ::= "exists" "(" expr ")" - | "exists" "(" var_decls ("|" formula)? ("|" formula)? ")" - | "forall" "(" var_decls ("|" formula)? "|" formula ")" - | "forex" "(" var_decls ("|" formula)? "|" formula ")" - - comparison ::= expr compop expr - - compop ::= "=" | "!=" | "<" | ">" | "<=" | ">=" - - instanceof ::= expr "instanceof" type - - inrange ::= expr "in" range - - call ::= predicateRef (closure)? "(" (exprs)? ")" - | primary "." predicateName (closure)? "(" (exprs)? ")" - - closure ::= "*" | "+" - - expr ::= dontcare - | unop - | binop - | cast - | primary - - - primary ::= eparen - | literal - | variable - | super_expr - | postfix_cast - | callwithresults - | aggregation - | any - | range - | setliteral - - eparen ::= "(" expr ")" - - dontcare ::= "_" - - literal ::= "false" | "true" | int | float | string - - unop ::= "+" expr - | "-" expr - - binop ::= expr "+" expr - | expr "-" expr - | expr "*" expr - | expr "/" expr - | expr "%" expr - - variable ::= varname | "this" | "result" - - super_expr ::= "super" | type "." "super" - - cast ::= "(" type ")" expr - - postfix_cast ::= primary "." "(" type ")" - - aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" - | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" - | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" - - aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" - - aggorderbys ::= aggorderby ("," aggorderby)* - - aggorderby ::= expr ("asc" | "desc")? - - any ::= "any" "(" var_decls ("|" (formula)? ("|" expr)?)? ")" - - callwithresults ::= predicateRef (closure)? "(" (exprs)? ")" - | primary "." predicateName (closure)? "(" (exprs)? ")" - - range ::= "[" expr ".." expr "]" - - setliteral ::= "[" expr ("," expr)* "]" - - simpleId ::= lowerId | upperId - - modulename ::= simpleId - - classname ::= upperId - - dbasetype ::= atLowerId - - predicateRef ::= (moduleId "::")? literalId - - predicateName ::= lowerId - - varname ::= simpleId - - literalId ::= lowerId | atLowerId | "any" | "none" diff --git a/docs/language/ql-spec/qldoc.rst b/docs/language/ql-spec/qldoc.rst deleted file mode 100644 index d2ca924598e..00000000000 --- a/docs/language/ql-spec/qldoc.rst +++ /dev/null @@ -1,50 +0,0 @@ -QLDoc comment specification -=========================== - -This document is a formal specification for QLDoc comments. - -About QLDoc comments --------------------- - -You can provide documentation for a QL entity by adding a QLDoc comment in the source file. The QLDoc comment is displayed as pop-up information in QL editors, for example when you hover over a predicate name. - -Notation --------- - -A 'QLDoc comment' is a valid QL comment that begins with ``/**`` and ends with ``*/``. - -The 'content' of a QLDoc comment is the textual body of the comment, omitting the initial ``/**``, the trailing ``*/``, and the leading whitespace followed by ``*`` on each internal line. - -A QLDoc comment 'precedes' the next QL syntax element after it in the file. - -Association ------------ - -A QLDoc comment may be 'associated with' any of the following QL syntax elements: - -- Class declarations -- Non-member predicate declarations -- Member predicate declarations -- Modules - -For class and predicate declarations, the associated QLDoc comment (if any) is the closest preceding QLDoc comment. - -For modules, the associated QLDoc comment (if any) is the QLDoc comment which is the first element in the file, and moreover is not associated with any other QL element. - -Inheritance ------------ - -If a member predicate has no directly associated QLDoc and overrides a set of member predicates which all have the same QLDoc, then the member predicate inherits that QLDoc. - -Content -------- - -The content of a QLDoc comment is interpreted as standard Markdown, with the following extensions: - -- Fenced code blocks using backticks. -- Automatic interpretation of links and email addresses. -- Use of appropriate characters for ellipses, dashes, apostrophes, and quotes. - -The content of a QLDoc comment may contain metadata tags as follows: - -The tag begins with any number of whitespace characters, followed by an '@' sign. At this point there may be any number of non-whitespace characters, which form the key of the tag. Then, a single whitespace character which separates the key from the value. The value of the tag is formed by the remainder of the line, and any subsequent lines until another '@' tag is seen, or the end of the content is reached. From 2d864aaf1bd565894c941033902de55fac8fb4a3 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 1 Apr 2020 10:33:44 +0100 Subject: [PATCH 234/459] JS: Add failing test --- .../ql/test/library-tests/RangeAnalysis/DeadBranch.expected | 1 + javascript/ql/test/library-tests/RangeAnalysis/constants.js | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected b/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected index e69de29bb2d..bd592551dce 100644 --- a/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected +++ b/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected @@ -0,0 +1 @@ +| constants.js:12:27:12:31 | // OK | Error: analysis claims x >= 1_000 is always false | diff --git a/javascript/ql/test/library-tests/RangeAnalysis/constants.js b/javascript/ql/test/library-tests/RangeAnalysis/constants.js index 9e1a3b914e3..decd2a19e9a 100644 --- a/javascript/ql/test/library-tests/RangeAnalysis/constants.js +++ b/javascript/ql/test/library-tests/RangeAnalysis/constants.js @@ -6,3 +6,8 @@ function f() { if (two > one) {} // NOT OK - always true if (two <= one) {} // NOT OK - always false } + +function underscores(x) { + if (x >= 1_000_000) return; // OK + if (x >= 1_000) return; // OK +} From 9888f15a298dea77857d1cbddb867467adc29b85 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 1 Apr 2020 10:36:13 +0100 Subject: [PATCH 235/459] JS: Add test showing root cause of problem --- .../Constants/Constants.expected | 34 +++++++++++++++++++ .../test/library-tests/Constants/Constants.ql | 2 ++ .../ql/test/library-tests/Constants/tst.js | 3 ++ 3 files changed, 39 insertions(+) diff --git a/javascript/ql/test/library-tests/Constants/Constants.expected b/javascript/ql/test/library-tests/Constants/Constants.expected index 75a63830277..35ce0fc93ff 100644 --- a/javascript/ql/test/library-tests/Constants/Constants.expected +++ b/javascript/ql/test/library-tests/Constants/Constants.expected @@ -1,3 +1,33 @@ +getIntValue +| tst2.ts:1:21:1:21 | 1 | 1 | +| tst.js:6:1:6:1 | 1 | 1 | +| tst.js:11:1:11:2 | -1 | -1 | +| tst.js:11:2:11:2 | 1 | 1 | +| tst.js:12:2:12:2 | 0 | 0 | +| tst.js:26:3:26:3 | 0 | 0 | +| tst.js:29:6:29:6 | 0 | 0 | +| tst.js:35:1:35:1 | 1 | 1 | +| tst.js:35:5:35:5 | 2 | 2 | +| tst.js:35:9:35:9 | 3 | 3 | +| tst.js:37:1:37:3 | (1) | 1 | +| tst.js:37:2:37:2 | 1 | 1 | +| tst.js:39:4:39:4 | 1 | 1 | +| tst.js:40:1:40:1 | 1 | 1 | +| tst.js:42:1:42:1 | 1 | 1 | +| tst.js:42:4:42:4 | 2 | 2 | +| tst.js:42:7:42:7 | 3 | 3 | +| tst.js:43:4:43:4 | 2 | 2 | +| tst.js:43:7:43:7 | 3 | 3 | +| tst.js:44:1:44:1 | 1 | 1 | +| tst.js:44:7:44:7 | 3 | 3 | +| tst.js:45:1:45:1 | 1 | 1 | +| tst.js:45:4:45:4 | 2 | 2 | +| tst.js:47:5:47:5 | 1 | 1 | +| tst.js:48:7:48:7 | 1 | 1 | +| tst.js:49:6:49:6 | 1 | 1 | +| tst.js:52:5:52:9 | 1_000 | 1 | +| tst.js:53:5:53:13 | 1_000_123 | 1 | +#select | tst2.ts:1:13:1:21 | 1 | | tst2.ts:1:21:1:21 | 1 | | tst.js:1:1:1:3 | "a" | @@ -61,3 +91,7 @@ | tst.js:48:1:48:7 | x.p = 1 | | tst.js:48:7:48:7 | 1 | | tst.js:49:6:49:6 | 1 | +| tst.js:52:1:52:9 | x = 1_000 | +| tst.js:52:5:52:9 | 1_000 | +| tst.js:53:1:53:13 | x = 1_000_123 | +| tst.js:53:5:53:13 | 1_000_123 | diff --git a/javascript/ql/test/library-tests/Constants/Constants.ql b/javascript/ql/test/library-tests/Constants/Constants.ql index dcd49275a86..903fe90bc91 100644 --- a/javascript/ql/test/library-tests/Constants/Constants.ql +++ b/javascript/ql/test/library-tests/Constants/Constants.ql @@ -2,3 +2,5 @@ import javascript from ConstantExpr c select c + +query int getIntValue(Expr e) { result = e.getIntValue() } diff --git a/javascript/ql/test/library-tests/Constants/tst.js b/javascript/ql/test/library-tests/Constants/tst.js index 0a24e13abc1..9e6e80ffaeb 100644 --- a/javascript/ql/test/library-tests/Constants/tst.js +++ b/javascript/ql/test/library-tests/Constants/tst.js @@ -48,3 +48,6 @@ x = 1; x.p = 1; x += 1; x += x; + +x = 1_000; +x = 1_000_123; From b5e110e39eb634edf7f708edbe5b6e49b70f037b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 1 Apr 2020 12:24:42 +0100 Subject: [PATCH 236/459] JS: Fix value of numeric literals containing underscores --- .../src/com/semmle/jcorn/ESNextParser.java | 1 + .../src/com/semmle/jcorn/Parser.java | 11 +- .../Constants/Constants.expected | 112 +++++++++++++++++- .../test/library-tests/Constants/Constants.ql | 4 + .../ql/test/library-tests/Constants/tst.js | 9 ++ .../RangeAnalysis/DeadBranch.expected | 1 - 6 files changed, 134 insertions(+), 4 deletions(-) diff --git a/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java b/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java index f750013067b..6ad5cca137e 100644 --- a/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java @@ -482,6 +482,7 @@ public class ESNextParser extends JSXParser { if (code == '_') { if (underscoreAllowed) { + seenUnderscoreNumericSeparator = true; // no adjacent underscores underscoreAllowed = false; ++this.pos; diff --git a/javascript/extractor/src/com/semmle/jcorn/Parser.java b/javascript/extractor/src/com/semmle/jcorn/Parser.java index eee2e172a6d..a8348c3c307 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Parser.java +++ b/javascript/extractor/src/com/semmle/jcorn/Parser.java @@ -145,6 +145,11 @@ public class Parser { private Stack labels; protected int yieldPos, awaitPos; + /** + * Set to true by {@link ESNextParser#readInt} if the parsed integer contains an underscore. + */ + protected boolean seenUnderscoreNumericSeparator = false; + /** * For readability purposes, we pass this instead of false as the argument to the * hasDeclareKeyword parameter (which only exists in TypeScript). @@ -654,7 +659,7 @@ public class Parser { case 58: ++this.pos; return this.finishToken(TokenType.colon); - case 35: + case 35: ++this.pos; return this.finishToken(TokenType.pound); case 63: @@ -847,6 +852,10 @@ public class Parser { } String str = inputSubstring(start, this.pos); + if (seenUnderscoreNumericSeparator) { + str = str.replace("_", ""); + seenUnderscoreNumericSeparator = false; + } Number val = null; if (isFloat) val = parseFloat(str); else if (!octal || str.length() == 1) val = parseInt(str, 10); diff --git a/javascript/ql/test/library-tests/Constants/Constants.expected b/javascript/ql/test/library-tests/Constants/Constants.expected index 35ce0fc93ff..cb8ff2418bc 100644 --- a/javascript/ql/test/library-tests/Constants/Constants.expected +++ b/javascript/ql/test/library-tests/Constants/Constants.expected @@ -25,8 +25,98 @@ getIntValue | tst.js:47:5:47:5 | 1 | 1 | | tst.js:48:7:48:7 | 1 | 1 | | tst.js:49:6:49:6 | 1 | 1 | -| tst.js:52:5:52:9 | 1_000 | 1 | -| tst.js:53:5:53:13 | 1_000_123 | 1 | +| tst.js:52:5:52:9 | 1_000 | 1000 | +| tst.js:53:5:53:13 | 1_000_123 | 1000123 | +| tst.js:54:5:54:17 | 1_000_000_000 | 1000000000 | +| tst.js:56:5:56:10 | 123_00 | 12300 | +| tst.js:57:5:57:10 | 12_300 | 12300 | +| tst.js:58:5:58:12 | 12345_00 | 1234500 | +| tst.js:59:5:59:12 | 123_4500 | 1234500 | +| tst.js:60:5:60:13 | 1_234_500 | 1234500 | +| tst.js:62:5:62:14 | 0xaa_bb_cc | 11189196 | +getFloatValue +| tst2.ts:1:21:1:21 | 1 | 1.0 | +| tst.js:6:1:6:1 | 1 | 1.0 | +| tst.js:11:2:11:2 | 1 | 1.0 | +| tst.js:12:2:12:2 | 0 | 0.0 | +| tst.js:26:3:26:3 | 0 | 0.0 | +| tst.js:29:6:29:6 | 0 | 0.0 | +| tst.js:35:1:35:1 | 1 | 1.0 | +| tst.js:35:5:35:5 | 2 | 2.0 | +| tst.js:35:9:35:9 | 3 | 3.0 | +| tst.js:37:2:37:2 | 1 | 1.0 | +| tst.js:39:4:39:4 | 1 | 1.0 | +| tst.js:40:1:40:1 | 1 | 1.0 | +| tst.js:42:1:42:1 | 1 | 1.0 | +| tst.js:42:4:42:4 | 2 | 2.0 | +| tst.js:42:7:42:7 | 3 | 3.0 | +| tst.js:43:4:43:4 | 2 | 2.0 | +| tst.js:43:7:43:7 | 3 | 3.0 | +| tst.js:44:1:44:1 | 1 | 1.0 | +| tst.js:44:7:44:7 | 3 | 3.0 | +| tst.js:45:1:45:1 | 1 | 1.0 | +| tst.js:45:4:45:4 | 2 | 2.0 | +| tst.js:47:5:47:5 | 1 | 1.0 | +| tst.js:48:7:48:7 | 1 | 1.0 | +| tst.js:49:6:49:6 | 1 | 1.0 | +| tst.js:52:5:52:9 | 1_000 | 1000.0 | +| tst.js:53:5:53:13 | 1_000_123 | 1000123.0 | +| tst.js:54:5:54:17 | 1_000_000_000 | 1.0E9 | +| tst.js:55:5:55:18 | 101_475_938.38 | 1.0147593838E8 | +| tst.js:56:5:56:10 | 123_00 | 12300.0 | +| tst.js:57:5:57:10 | 12_300 | 12300.0 | +| tst.js:58:5:58:12 | 12345_00 | 1234500.0 | +| tst.js:59:5:59:12 | 123_4500 | 1234500.0 | +| tst.js:60:5:60:13 | 1_234_500 | 1234500.0 | +| tst.js:61:5:61:10 | 1e1_00 | 1.0E100 | +| tst.js:62:5:62:14 | 0xaa_bb_cc | 1.1189196E7 | +getLiteralValue +| tst2.ts:1:21:1:21 | 1 | 1 | +| tst.js:1:1:1:3 | "a" | a | +| tst.js:2:1:2:3 | "b" | b | +| tst.js:2:7:2:9 | "c" | c | +| tst.js:3:1:3:3 | "d" | d | +| tst.js:3:7:3:9 | "e" | e | +| tst.js:3:13:3:15 | "f" | f | +| tst.js:6:1:6:1 | 1 | 1 | +| tst.js:8:1:8:5 | false | false | +| tst.js:9:1:9:4 | true | true | +| tst.js:11:2:11:2 | 1 | 1 | +| tst.js:12:2:12:2 | 0 | 0 | +| tst.js:14:1:14:4 | null | null | +| tst.js:20:1:20:3 | /x/ | /x/ | +| tst.js:24:5:24:7 | "x" | x | +| tst.js:26:3:26:3 | 0 | 0 | +| tst.js:29:6:29:6 | 0 | 0 | +| tst.js:35:1:35:1 | 1 | 1 | +| tst.js:35:5:35:5 | 2 | 2 | +| tst.js:35:9:35:9 | 3 | 3 | +| tst.js:37:2:37:2 | 1 | 1 | +| tst.js:39:4:39:4 | 1 | 1 | +| tst.js:40:1:40:1 | 1 | 1 | +| tst.js:42:1:42:1 | 1 | 1 | +| tst.js:42:4:42:4 | 2 | 2 | +| tst.js:42:7:42:7 | 3 | 3 | +| tst.js:43:4:43:4 | 2 | 2 | +| tst.js:43:7:43:7 | 3 | 3 | +| tst.js:44:1:44:1 | 1 | 1 | +| tst.js:44:7:44:7 | 3 | 3 | +| tst.js:45:1:45:1 | 1 | 1 | +| tst.js:45:4:45:4 | 2 | 2 | +| tst.js:47:5:47:5 | 1 | 1 | +| tst.js:48:7:48:7 | 1 | 1 | +| tst.js:49:6:49:6 | 1 | 1 | +| tst.js:52:5:52:9 | 1_000 | 1000 | +| tst.js:53:5:53:13 | 1_000_123 | 1000123 | +| tst.js:54:5:54:17 | 1_000_000_000 | 1000000000 | +| tst.js:55:5:55:18 | 101_475_938.38 | 1.0147593838E8 | +| tst.js:56:5:56:10 | 123_00 | 12300 | +| tst.js:57:5:57:10 | 12_300 | 12300 | +| tst.js:58:5:58:12 | 12345_00 | 1234500 | +| tst.js:59:5:59:12 | 123_4500 | 1234500 | +| tst.js:60:5:60:13 | 1_234_500 | 1234500 | +| tst.js:61:5:61:10 | 1e1_00 | 1.0E100 | +| tst.js:62:5:62:14 | 0xaa_bb_cc | 11189196 | #select | tst2.ts:1:13:1:21 | 1 | | tst2.ts:1:21:1:21 | 1 | @@ -95,3 +185,21 @@ getIntValue | tst.js:52:5:52:9 | 1_000 | | tst.js:53:1:53:13 | x = 1_000_123 | | tst.js:53:5:53:13 | 1_000_123 | +| tst.js:54:1:54:17 | x = 1_000_000_000 | +| tst.js:54:5:54:17 | 1_000_000_000 | +| tst.js:55:1:55:18 | x = 101_475_938.38 | +| tst.js:55:5:55:18 | 101_475_938.38 | +| tst.js:56:1:56:10 | x = 123_00 | +| tst.js:56:5:56:10 | 123_00 | +| tst.js:57:1:57:10 | x = 12_300 | +| tst.js:57:5:57:10 | 12_300 | +| tst.js:58:1:58:12 | x = 12345_00 | +| tst.js:58:5:58:12 | 12345_00 | +| tst.js:59:1:59:12 | x = 123_4500 | +| tst.js:59:5:59:12 | 123_4500 | +| tst.js:60:1:60:13 | x = 1_234_500 | +| tst.js:60:5:60:13 | 1_234_500 | +| tst.js:61:1:61:10 | x = 1e1_00 | +| tst.js:61:5:61:10 | 1e1_00 | +| tst.js:62:1:62:14 | x = 0xaa_bb_cc | +| tst.js:62:5:62:14 | 0xaa_bb_cc | diff --git a/javascript/ql/test/library-tests/Constants/Constants.ql b/javascript/ql/test/library-tests/Constants/Constants.ql index 903fe90bc91..0f8b338d9ad 100644 --- a/javascript/ql/test/library-tests/Constants/Constants.ql +++ b/javascript/ql/test/library-tests/Constants/Constants.ql @@ -4,3 +4,7 @@ from ConstantExpr c select c query int getIntValue(Expr e) { result = e.getIntValue() } + +query float getFloatValue(NumberLiteral e) { result = e.getFloatValue() } + +query string getLiteralValue(Literal lit) { result = lit.getValue() } diff --git a/javascript/ql/test/library-tests/Constants/tst.js b/javascript/ql/test/library-tests/Constants/tst.js index 9e6e80ffaeb..06304139c75 100644 --- a/javascript/ql/test/library-tests/Constants/tst.js +++ b/javascript/ql/test/library-tests/Constants/tst.js @@ -51,3 +51,12 @@ x += x; x = 1_000; x = 1_000_123; +x = 1_000_000_000; +x = 101_475_938.38; +x = 123_00; +x = 12_300; +x = 12345_00; +x = 123_4500; +x = 1_234_500; +x = 1e1_00; +x = 0xaa_bb_cc; diff --git a/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected b/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected index bd592551dce..e69de29bb2d 100644 --- a/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected +++ b/javascript/ql/test/library-tests/RangeAnalysis/DeadBranch.expected @@ -1 +0,0 @@ -| constants.js:12:27:12:31 | // OK | Error: analysis claims x >= 1_000 is always false | From 541ff40d247c991f62d7cc4ada7439fd7b309fe0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 1 Apr 2020 12:26:30 +0100 Subject: [PATCH 237/459] JS: Bump extractor version string --- javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 4e9122fa053..904969a168f 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -38,7 +38,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2020-02-14"; + public static final String EXTRACTOR_VERSION = "2020-04-01"; public static final Pattern NEWLINE = Pattern.compile("\n"); From 79068d5e6802c24fcc1a0113dfd48b86191a9872 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 1 Apr 2020 12:33:45 +0100 Subject: [PATCH 238/459] Update link --- docs/language/learn-ql/writing-queries/debugging-queries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/writing-queries/debugging-queries.rst b/docs/language/learn-ql/writing-queries/debugging-queries.rst index 3baac5e4bea..c5fd01c67fc 100644 --- a/docs/language/learn-ql/writing-queries/debugging-queries.rst +++ b/docs/language/learn-ql/writing-queries/debugging-queries.rst @@ -10,7 +10,7 @@ This topic offers some simple tips on how to avoid common problems that can affe Before reading the tips below, it is worth reiterating a few important points about CodeQL and the QL language: - CodeQL `predicates `__ and `classes `__ are evaluated to database `tables `__. Large predicates generate large tables with many rows, and are therefore expensive to compute. -- The QL language is implemented using standard database operations and `relational algebra `__ (such as join, projection, and union). For further information about query languages and databases, see :doc:`About QL <../about-ql>`. +- The QL language is implemented using standard database operations and `relational algebra `__ (such as join, projection, and union). For further information about query languages and databases, see `About the QL language `__. - Queries are evaluated *bottom-up*, which means that a predicate is not evaluated until *all* of the predicates that it depends on are evaluated. For more information on query evaluation, see `Evaluation of QL programs `__ in the QL handbook. Performance tips From 554bb767465b38721c66088caa14d9161495126b Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 1 Apr 2020 14:16:35 +0200 Subject: [PATCH 239/459] Python: Fix up (hopefully) the last file that needs autoformatting. --- .../library-tests/examples/custom-sanitizer/TestTaint.ql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql index 81357d18fc7..4df37b9cdfa 100644 --- a/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql +++ b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql @@ -2,8 +2,8 @@ import python import semmle.python.security.TaintTracking import Taint -from Call call, Expr arg, - boolean expected_taint, boolean has_taint, string test_res, +from + Call call, Expr arg, boolean expected_taint, boolean has_taint, string test_res, string taint_string where call.getLocation().getFile().getShortName() = "test.py" and @@ -26,6 +26,6 @@ where has_taint = true ) and if expected_taint = has_taint then test_res = "ok" else test_res = "failure" - // if expected_taint = has_taint then test_res = "✓" else test_res = "✕" +// if expected_taint = has_taint then test_res = "✓" else test_res = "✕" select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string, test_res From fa7dc32dee44e9d5773f6122b3247a3ed9b6cb16 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 1 Apr 2020 14:46:52 +0200 Subject: [PATCH 240/459] C++: Remove dependency on implementation of models in TranslatedCall --- .../raw/internal/TranslatedCall.qll | 29 +++---------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 9de3d6efa2b..088cb7fa4cd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -7,7 +7,6 @@ private import InstructionTag private import TranslatedElement private import TranslatedExpr private import TranslatedFunction -private import semmle.code.cpp.models.implementations.Allocation /** * The IR translation of a call to a function. The call may be from an actual @@ -346,7 +345,7 @@ class TranslatedStructorCall extends TranslatedFunctionCall { override predicate hasQualifier() { any() } } -abstract class TranslatedAllocationSideEffects extends TranslatedSideEffects, +class TranslatedAllocationSideEffects extends TranslatedSideEffects, TTranslatedAllocationSideEffects { AllocationExpr expr; @@ -377,32 +376,12 @@ abstract class TranslatedAllocationSideEffects extends TranslatedSideEffects, operandTag = addressOperand() and result = getPrimaryInstructionForSideEffect(OnlyInstructionTag()) } -} - -class TranslatedCallAllocationSideEffects extends TranslatedAllocationSideEffects { - override CallAllocationExpr expr; override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { tag = OnlyInstructionTag() and - result = getTranslatedExpr(expr).getInstruction(CallTag()) - } -} - -class TranslatedNewAllocationSideEffects extends TranslatedAllocationSideEffects { - override NewAllocationExpr expr; - - override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { - tag = OnlyInstructionTag() and - result = getTranslatedAllocatorCall(expr).getInstruction(CallTag()) - } -} - -class TranslatedNewArrayAllocationSideEffects extends TranslatedAllocationSideEffects { - override NewArrayAllocationExpr expr; - - override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { - tag = OnlyInstructionTag() and - result = getTranslatedAllocatorCall(expr).getInstruction(CallTag()) + if expr instanceof NewOrNewArrayExpr + then result = getTranslatedAllocatorCall(expr).getInstruction(CallTag()) + else result = getTranslatedExpr(expr).getInstruction(CallTag()) } } From 119d4a40a0462f2d2760e707c331f21355119906 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 1 Apr 2020 14:29:28 +0100 Subject: [PATCH 241/459] C++: Fix unintended consequence in IR. --- .../ir/implementation/raw/internal/TranslatedCall.qll | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index fb7dc173812..f2d098afbcc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -343,6 +343,11 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { expr.getTarget() instanceof AllocationFunction and + not exists(NewOrNewArrayExpr newExpr | + // we synthesize allocator calls for `new` and `new[]`, so don't add instructions to + // the existing allocator call when it exists. + newExpr.getAllocatorCall() = expr + ) and opcode instanceof Opcode::InitializeDynamicAllocation and tag = OnlyInstructionTag() and type = getUnknownType() @@ -358,6 +363,11 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { tag = OnlyInstructionTag() and kind = gotoEdge() and expr.getTarget() instanceof AllocationFunction and + not exists(NewOrNewArrayExpr newExpr | + // we synthesize allocator calls for `new` and `new[]`, so don't add instructions to + // the existing allocator call when it exists. + newExpr.getAllocatorCall() = expr + ) and if exists(getChild(0)) then result = getChild(0).getFirstInstruction() else result = getParent().getChildSuccessor(this) From 9a55d42639f16c64aa1fba2fe293706f2ebde697 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 1 Apr 2020 15:29:45 +0200 Subject: [PATCH 242/459] C++: QLDoc in DefaultTaintTracking These docs are mostly copied and adapted from `DefaultTaintTrackingImpl.qll`. --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index d932ad30b87..893de1c2af9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -348,6 +348,16 @@ private Element adjustedSink(DataFlow::Node sink) { result.(AssignOperation).getAnOperand() = sink.asExpr() } +/** + * Holds if `tainted` may contain taint from `source`. + * + * A tainted expression is either directly user input, or is + * computed from user input in a way that users can probably + * control the exact output of the computation. + * + * This doesn't include data flow through global variables. + * If you need that you must call `taintedIncludingGlobalVars`. + */ cached predicate tainted(Expr source, Element tainted) { exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink | @@ -356,6 +366,21 @@ predicate tainted(Expr source, Element tainted) { ) } +/** + * Holds if `tainted` may contain taint from `source`, where the taint passed + * through a global variable named `globalVar`. + * + * A tainted expression is either directly user input, or is + * computed from user input in a way that users can probably + * control the exact output of the computation. + * + * This version gives the same results as tainted but also includes + * data flow through global variables. + * + * The parameter `globalVar` is the qualified name of the last global variable + * used to move the value from source to tainted. If the taint did not pass + * through a global variable, then `globalVar = ""`. + */ cached predicate taintedIncludingGlobalVars(Expr source, Element tainted, string globalVar) { tainted(source, tainted) and @@ -373,8 +398,19 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global ) } +/** + * Gets the global variable whose qualified name is `id`. Use this predicate + * together with `taintedIncludingGlobalVars`. + */ GlobalOrNamespaceVariable globalVarFromId(string id) { id = result.getQualifiedName() } +/** + * Resolve potential target function(s) for `call`. + * + * If `call` is a call through a function pointer (`ExprCall`) or + * targets a virtual method, simple data flow analysis is performed + * in order to identify target(s). + */ Function resolveCall(Call call) { exists(CallInstruction callInstruction | callInstruction.getAST() = call and From d9f04a8da4563d4b5e11dc94a7c34cfae3813b3b Mon Sep 17 00:00:00 2001 From: james Date: Wed, 1 Apr 2020 15:11:05 +0100 Subject: [PATCH 243/459] docs: update query console link text --- .../beginner/catch-the-fire-starter.rst | 4 +-- .../learn-ql/beginner/cross-the-river.rst | 6 ++-- .../beginner/crown-the-rightful-heir.rst | 4 +-- .../learn-ql/beginner/find-the-thief.rst | 6 ++-- .../learn-ql/cpp/conversions-classes.rst | 10 +++--- docs/language/learn-ql/cpp/dataflow.rst | 2 +- .../learn-ql/cpp/expressions-types.rst | 10 +++--- .../learn-ql/cpp/function-classes.rst | 8 ++--- .../learn-ql/cpp/introduce-libraries-cpp.rst | 2 +- .../cpp/private-field-initialization.rst | 4 +-- .../learn-ql/cpp/zero-space-terminator.rst | 2 +- docs/language/learn-ql/csharp/dataflow.rst | 2 +- .../csharp/introduce-libraries-csharp.rst | 2 +- docs/language/learn-ql/index.rst | 2 +- docs/language/learn-ql/introduction-to-ql.rst | 12 +++---- docs/language/learn-ql/java/annotations.rst | 8 ++--- docs/language/learn-ql/java/call-graph.rst | 12 +++---- docs/language/learn-ql/java/dataflow.rst | 2 +- .../learn-ql/java/expressions-statements.rst | 6 ++-- .../java/introduce-libraries-java.rst | 32 ++++++++--------- docs/language/learn-ql/java/javadoc.rst | 4 +-- .../learn-ql/java/source-locations.rst | 6 ++-- .../learn-ql/java/types-class-hierarchy.rst | 10 +++--- .../language/learn-ql/javascript/dataflow.rst | 2 +- .../learn-ql/javascript/flow-labels.rst | 2 +- .../javascript/introduce-libraries-js.rst | 36 +++++++++---------- .../javascript/introduce-libraries-ts.rst | 8 ++--- .../learn-ql/javascript/type-tracking.rst | 2 +- .../language/learn-ql/python/control-flow.rst | 6 ++-- docs/language/learn-ql/python/functions.rst | 8 ++--- .../python/introduce-libraries-python.rst | 12 +++---- .../learn-ql/python/pointsto-type-infer.rst | 12 +++---- .../python/statements-expressions.rst | 10 +++--- .../introduction-to-queries.rst | 2 +- 34 files changed, 128 insertions(+), 128 deletions(-) diff --git a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst index 95f2e86f974..e1603303455 100644 --- a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -103,7 +103,7 @@ Now try applying ``isAllowedIn(string region)`` to a person ``p``. If ``p`` is n You know that the fire starters live in the south *and* that they must have been able to travel to the north. Write a query to find the possible suspects. You could also extend the ``select`` clause to list the age of the suspects. That way you can clearly see that all the children have been excluded from the list. -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ You can now continue to gather more clues and find out which of your suspects started the fire... @@ -140,7 +140,7 @@ The predicate ``isBald`` is defined to take a ``Person``, so it can also take a You can now write a query to select the bald southerners who are allowed into the north. -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ You have found the two fire starters! They are arrested and the villagers are once again impressed with your work. diff --git a/docs/language/learn-ql/beginner/cross-the-river.rst b/docs/language/learn-ql/beginner/cross-the-river.rst index 7901ae00412..3f5307d98d5 100644 --- a/docs/language/learn-ql/beginner/cross-the-river.rst +++ b/docs/language/learn-ql/beginner/cross-the-river.rst @@ -251,15 +251,15 @@ Here are some more example queries that solve the river crossing puzzle: #. This query uses a modified ``path`` variable to describe the resulting path in more detail. - ➤ `See solution in the query console `__ + ➤ `See solution in the query console on LGTM.com `__ #. This query models the man and the cargo items in a different way, using an `abstract `__ class and predicate. It also displays the resulting path in a more visual way. - ➤ `See solution in the query console `__ + ➤ `See solution in the query console on LGTM.com `__ #. This query introduces `algebraic datatypes `__ to model the situation, instead of defining everything as a subclass of ``string``. - ➤ `See solution in the query console `__ \ No newline at end of file + ➤ `See solution in the query console on LGTM.com `__ \ No newline at end of file diff --git a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst index 176a1b57155..14978dbd120 100644 --- a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst +++ b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst @@ -127,7 +127,7 @@ Here is one way to define ``relativeOf()``: Don't forget to use the predicate ``isDeceased()`` to find relatives that are still alive. -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ Select the true heir -------------------- @@ -140,7 +140,7 @@ To decide who should inherit the king's fortune, the villagers carefully read th As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief ` and :doc:`Catch the fire starter ` tutorials). -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ Experimental explorations ------------------------- diff --git a/docs/language/learn-ql/beginner/find-the-thief.rst b/docs/language/learn-ql/beginner/find-the-thief.rst index 3172f98e511..0c168604339 100644 --- a/docs/language/learn-ql/beginner/find-the-thief.rst +++ b/docs/language/learn-ql/beginner/find-the-thief.rst @@ -46,7 +46,7 @@ You start asking some creative questions and making notes of the answers so you There is too much information to search through by hand, so you decide to use your newly acquired QL skills to help you with your investigation... -#. Open the `query console `__ to get started. +#. Open the `query console on LGTM.com `__ to get started. #. Select a language and a demo project. For this tutorial, any language and project will do. #. Delete the default code ``import select "hello world"``. @@ -205,7 +205,7 @@ Hints Once you have finished, you will have a list of possible suspects. One of those people must be the thief! -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ .. pull-quote:: @@ -287,7 +287,7 @@ You can now translate the remaining questions into QL: Have you found the thief? -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ What next? ---------- diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index 054d082f9ef..ec00469091e 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -163,7 +163,7 @@ Our starting point for the query is pairs of a base class and a derived class, c where derived.getABaseClass+() = base select base, derived, "The second class is derived from the first." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Note that the transitive closure symbol ``+`` indicates that ``Class.getABaseClass()`` may be followed one or more times, rather than only accepting a direct base class. @@ -175,7 +175,7 @@ A lot of the results are uninteresting template parameters. You can remove those and not exists(base.getATemplateArgument()) and not exists(derived.getATemplateArgument()) -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Finding derived classes with destructors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -194,7 +194,7 @@ Now we can extend the query to find derived classes with destructors, using the and d2 = derived.getDestructor() select base, derived, "The second class is derived from the first, and both have a destructor." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Notice that getting the destructor implicitly asserts that one exists. As a result, this version of the query returns fewer results than before. @@ -214,7 +214,7 @@ Our last change is to use ``Function.isVirtual()`` to find cases where the base and not d1.isVirtual() select d1, "This destructor should probably be virtual." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ That completes the query. @@ -227,4 +227,4 @@ Further reading - Take a look at the :doc:`Analyzing data flow in C and C++ ` tutorial. - Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases `, and :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index b4bffe595ea..fe205dd3701 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -300,7 +300,7 @@ Further reading - Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases ` and :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. Answers ------- diff --git a/docs/language/learn-ql/cpp/expressions-types.rst b/docs/language/learn-ql/cpp/expressions-types.rst index 5894bccb113..a2a3d653c3b 100644 --- a/docs/language/learn-ql/cpp/expressions-types.rst +++ b/docs/language/learn-ql/cpp/expressions-types.rst @@ -21,7 +21,7 @@ In the following example we find instances of ``AssignExpr`` which assign the co where e.getRValue().getValue().toInt() = 0 select e, "Assigning the value 0 to something." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ The ``where`` clause in this example gets the expression on the right side of the assignment, ``getRValue()``, and compares it with zero. Notice that there are no checks to make sure that the right side of the assignment is an integer or that it has a value (that is, it is compile-time constant, rather than a variable). For expressions where either of these assumptions is wrong, the associated predicate simply does not return anything and the ``where`` clause will not produce a result. You could think of it as if there is an implicit ``exists(e.getRValue().getValue().toInt())`` at the beginning of this line. @@ -47,7 +47,7 @@ We can make the query more specific by defining a condition for the left side of and e.getLValue().getType().getUnspecifiedType() instanceof IntegralType select e, "Assigning the value 0 to an integer." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ This checks that the left side of the assignment has a type that is some kind of integer. Note the call to ``Type.getUnspecifiedType()``. This resolves ``typedef`` types to their underlying types so that the query finds assignments like this one: @@ -107,7 +107,7 @@ Unfortunately this would not quite work, because the loop initialization is actu and e.getLValue().getType().getUnspecifiedType() instanceof IntegralType select e, "Assigning the value 0 to an integer, inside a for loop initialization." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Finding assignments of 0 within the loop body ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -125,7 +125,7 @@ We can find assignments inside the loop body using similar code with the predica and e.getLValue().getType().getUnderlyingType() instanceof IntegralType select e, "Assigning the value 0 to an integer, inside a for loop body." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Note that we replaced ``e.getEnclosingStmt()`` with ``e.getEnclosingStmt().getParentStmt*()``, to find an assignment expression that is deeply nested inside the loop body. The transitive closure modifier ``*`` here indicates that ``Stmt.getParentStmt()`` may be followed zero or more times, rather than just once, giving us the statement, its parent statement, its parent's parent statement etc. @@ -135,4 +135,4 @@ Further reading - Explore other ways of finding types and statements using examples from the C/C++ cookbook for `types `__ and `statements `__. - Take a look at the :doc:`Conversions and classes in C and C++ ` and :doc:`Analyzing data flow in C and C++ ` tutorials. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/function-classes.rst b/docs/language/learn-ql/cpp/function-classes.rst index a6c15ebfa11..3748a3880dc 100644 --- a/docs/language/learn-ql/cpp/function-classes.rst +++ b/docs/language/learn-ql/cpp/function-classes.rst @@ -38,7 +38,7 @@ It might be more interesting to find functions that are not called, using the st where not exists(FunctionCall fc | fc.getTarget() = f) select f, "This function is never called." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ The new query finds functions that are not the target of any ``FunctionCall``—in other words, functions that are never called. You may be surprised by how many results the query finds. However, if you examine the results, you can see that many of the functions it finds are used indirectly. To create a query that finds only unused functions, we need to refine the query and exclude other ways of using a function. @@ -56,7 +56,7 @@ You can modify the query to remove functions where a function pointer is used to and not exists(FunctionAccess fa | fa.getTarget() = f) select f, "This function is never called, or referenced with a function pointer." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ This query returns fewer results. However, if you examine the results then you can probably still find potential refinements. @@ -78,7 +78,7 @@ This query uses ``Function`` and ``FunctionCall`` to find calls to the function and not fc.getArgument(1) instanceof StringLiteral select fc, "sprintf called with variable format string." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ This uses: @@ -95,4 +95,4 @@ Further reading - Explore other ways of finding functions using examples from the `C/C++ cookbook `__. - Take a look at some other tutorials: :doc:`Expressions, types and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 60e82d98f0a..960c98040fb 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -525,4 +525,4 @@ Further reading - Experiment with the worked examples in the CodeQL for C/C++ topics: :doc:`Functions in C and C++ `, :doc:`Expressions, types, and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/private-field-initialization.rst b/docs/language/learn-ql/cpp/private-field-initialization.rst index 4a1c858fd85..5d9e900f4e0 100644 --- a/docs/language/learn-ql/cpp/private-field-initialization.rst +++ b/docs/language/learn-ql/cpp/private-field-initialization.rst @@ -144,11 +144,11 @@ Finally we can simplify the query by using the transitive closure operator. In t and exists(c.getBlock()) select c, "Constructor does not initialize fields $@.", f, f.getName() -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Further reading --------------- - Take a look at another example: :doc:`Detecting a potential buffer overflow `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index 8c01a2e3cd9..7d1189de3b3 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -225,4 +225,4 @@ Further reading --------------- - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/csharp/dataflow.rst b/docs/language/learn-ql/csharp/dataflow.rst index 2cc60570f64..7824c1746b5 100644 --- a/docs/language/learn-ql/csharp/dataflow.rst +++ b/docs/language/learn-ql/csharp/dataflow.rst @@ -551,4 +551,4 @@ Further reading - Learn about the standard libraries used to write queries for C# in :doc:`Introducing the C# libraries `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index 1751657b99b..55611a6c02d 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1124,4 +1124,4 @@ Further reading - Visit :doc:`Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index dd74ebdc0a9..8008226b981 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -4,7 +4,7 @@ Learning CodeQL CodeQL is the code analysis platform used by security researchers to automate variant analysis. You can use CodeQL queries to explore code and quickly find variants of security vulnerabilities and bugs. These queries are easy to write and share–visit the topics below and `our open source repository on GitHub `__ to learn more. -You can also try out CodeQL in the `query console `__ on `LGTM.com `__. +You can also try out CodeQL in the `query console on LGTM.com `__. Here, you can query open source projects directly, without having to download CodeQL databases and libraries. CodeQL is based on a powerful query language called QL. The following topics help you understand QL in general, as well as how to use it when analyzing code with CodeQL. diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index e6ff509f570..c80785235f5 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -16,7 +16,7 @@ Basic syntax The basic syntax of QL will look familiar to anyone who has used SQL, but it is used somewhat differently. -A query is defined by a **select** clause, which specifies what the result of the query should be. You can try out the examples and exercises in this topic directly in LGTM. Open the `query console `__. Before you can run a query, you need to select a language and project to query (for these logic examples, any language and project will do). +A query is defined by a **select** clause, which specifies what the result of the query should be. You can try out the examples and exercises in this topic directly in LGTM. Open the `query console on LGTM.com `__. Before you can run a query, you need to select a language and project to query (for these logic examples, any language and project will do). Once you have selected a language, the query console is populated with the query: @@ -97,7 +97,7 @@ The exercises above all show queries with exactly one result, but in fact many q x*x + y*y = z*z select x, y, z -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ To simplify the query, we can introduce a class ``SmallInt`` representing the integers between 1 and 10. We can also define a predicate ``square()`` on integers in that class. Defining classes and predicates in this way makes it easy to reuse code without having to repeat it every time. @@ -112,7 +112,7 @@ To simplify the query, we can introduce a class ``SmallInt`` representing the in where x.square() + y.square() = z.square() select x, y, z -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Now that you've seen some general examples, let's use the CodeQL libraries to analyze projects. In particular, LGTM generates a database representing the code and then CodeQL is used to query this database. See `Database generation `__ for more details on how the database is built. @@ -132,7 +132,7 @@ Python where count(f.getAnArg()) > 7 select f -➤ `See this in the query console `__. The ``from`` clause defines a variable ``f`` representing a function. The ``where`` part limits the functions ``f`` to those with more than 7 arguments. Finally, the ``select`` clause lists these functions. +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``f`` representing a function. The ``where`` part limits the functions ``f`` to those with more than 7 arguments. Finally, the ``select`` clause lists these functions. JavaScript ~~~~~~~~~~ @@ -145,7 +145,7 @@ JavaScript where c.getText().regexpMatch("(?si).*\\bTODO\\b.*") select c -➤ `See this in the query console `__. The ``from`` clause defines a variable ``c`` representing a comment. The ``where`` part limits the comments ``c`` to those containing the word ``"TODO"``. The ``select`` clause lists these comments. +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``c`` representing a comment. The ``where`` part limits the comments ``c`` to those containing the word ``"TODO"``. The ``select`` clause lists these comments. Java ~~~~ @@ -158,7 +158,7 @@ Java where not exists(p.getAnAccess()) select p -➤ `See this in the query console `__. The ``from`` clause defines a variable ``p`` representing a parameter. The ``where`` clause finds unused parameters by limiting the parameters ``p`` to those which are not accessed. Finally, the ``select`` clause lists these parameters. +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``p`` representing a parameter. The ``where`` clause finds unused parameters by limiting the parameters ``p`` to those which are not accessed. Finally, the ``select`` clause lists these parameters. Learning CodeQL --------------- diff --git a/docs/language/learn-ql/java/annotations.rst b/docs/language/learn-ql/java/annotations.rst index a8c5fe93aa1..09588057617 100644 --- a/docs/language/learn-ql/java/annotations.rst +++ b/docs/language/learn-ql/java/annotations.rst @@ -49,7 +49,7 @@ We could then write this query to find all ``@SuppressWarnings`` annotations att anntp.hasQualifiedName("java.lang", "SuppressWarnings") select ann, ann.getValue("value") -➤ `See the full query in the query console `__. Several of the LGTM.com demo projects use the ``@SuppressWarnings`` annotation. Looking at the ``value``\ s of the annotation element returned by the query, we can see that the *apache/activemq* project uses the ``"rawtypes"`` value described above. +➤ `See the full query in the query console on LGTM.com `__. Several of the LGTM.com demo projects use the ``@SuppressWarnings`` annotation. Looking at the ``value``\ s of the annotation element returned by the query, we can see that the *apache/activemq* project uses the ``"rawtypes"`` value described above. As another example, this query finds all annotation types that only have a single annotation element, which has name ``value``: @@ -64,7 +64,7 @@ As another example, this query finds all annotation types that only have a singl ) select anntp -➤ `See the full query in the query console `__. +➤ `See the full query in the query console on LGTM.com `__. Example: Finding missing ``@Override`` annotations -------------------------------------------------- @@ -122,7 +122,7 @@ This makes it very easy to write our query for finding methods that override ano not overriding.getAnAnnotation() instanceof OverrideAnnotation select overriding, "Method overrides another method, but does not have an @Override annotation." -➤ `See this in the query console `__. In practice, this query may yield many results from compiled library code, which aren't very interesting. It's therefore a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available. +➤ `See this in the query console on LGTM.com `__. In practice, this query may yield many results from compiled library code, which aren't very interesting. It's therefore a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available. Example: Finding calls to deprecated methods -------------------------------------------- @@ -235,7 +235,7 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress and not call.getCaller().getAnAnnotation() instanceof SuppressDeprecationWarningAnnotation select call, "This call invokes a deprecated method." -➤ `See this in the query console `__. It's fairly common for projects to contain calls to methods that appear to be deprecated. +➤ `See this in the query console on LGTM.com `__. It's fairly common for projects to contain calls to methods that appear to be deprecated. Further reading --------------- diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index ab32cebdc8e..bdf713b7372 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -78,7 +78,7 @@ We can use the ``Callable`` class to write a query that finds methods that are n where not exists(Callable caller | caller.polyCalls(callee)) select callee -➤ `See this in the query console `__. This simple query typically returns a large number of results. +➤ `See this in the query console on LGTM.com `__. This simple query typically returns a large number of results. .. pull-quote:: @@ -97,7 +97,7 @@ Running this query on a typical Java project results in lots of hits in the Java callee.getCompilationUnit().fromSource() select callee, "Not called." -➤ `See this in the query console `__. This change reduces the number of results returned for most projects. +➤ `See this in the query console on LGTM.com `__. This change reduces the number of results returned for most projects. We might also notice several unused methods with the somewhat strange name ````: these are class initializers; while they are not explicitly called anywhere in the code, they are called implicitly whenever the surrounding class is loaded. Hence it makes sense to exclude them from our query. While we are at it, we can also exclude finalizers, which are similarly invoked implicitly: @@ -111,7 +111,7 @@ We might also notice several unused methods with the somewhat strange name ``") and not callee.hasName("finalize") select callee, "Not called." -➤ `See this in the query console `__. This also reduces the number of results returned by most projects. +➤ `See this in the query console on LGTM.com `__. This also reduces the number of results returned by most projects. We may also want to exclude public methods from our query, since they may be external API entry points: @@ -126,7 +126,7 @@ We may also want to exclude public methods from our query, since they may be ext not callee.isPublic() select callee, "Not called." -➤ `See this in the query console `__. This should have a more noticeable effect on the number of results returned. +➤ `See this in the query console on LGTM.com `__. This should have a more noticeable effect on the number of results returned. A further special case is non-public default constructors: in the singleton pattern, for example, a class is provided with private empty default constructor to prevent it from being instantiated. Since the very purpose of such constructors is their not being called, they should not be flagged up: @@ -142,7 +142,7 @@ A further special case is non-public default constructors: in the singleton patt not callee.(Constructor).getNumberOfParameters() = 0 select callee, "Not called." -➤ `See this in the query console `__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects. +➤ `See this in the query console on LGTM.com `__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects. Finally, on many Java projects there are methods that are invoked indirectly by reflection. So, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The QL Java library has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes: @@ -159,7 +159,7 @@ Finally, on many Java projects there are methods that are invoked indirectly by not callee.getDeclaringType() instanceof TestClass select callee, "Not called." -➤ `See this in the query console `__. This should give a further reduction in the number of results returned. +➤ `See this in the query console on LGTM.com `__. This should give a further reduction in the number of results returned. Further reading --------------- diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index 3550c1d9329..13aebe178f6 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -258,7 +258,7 @@ Further reading - Try the worked examples in these articles: :doc:`Navigating the call graph ` and :doc:`Working with source locations `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console on LGTM.com `__. Answers ------- diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index caa6c400852..20954cacd40 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -42,7 +42,7 @@ We'll start by writing a query that finds less-than expressions (CodeQL class `` expr.getRightOperand().getType().hasName("long") select expr -➤ `See this in the query console `__. This query usually finds results on most projects. +➤ `See this in the query console on LGTM.com `__. This query usually finds results on most projects. Notice that we use the predicate ``getType`` (available on all subclasses of ``Expr``) to determine the type of the operands. Types, in turn, define the ``hasName`` predicate, which allows us to identify the primitive types ``int`` and ``long``. As it stands, this query finds *all* less-than expressions comparing ``int`` and ``long``, but in fact we are only interested in comparisons that are part of a loop condition. Also, we want to filter out comparisons where either operand is constant, since these are less likely to be real bugs. The revised query looks like this: @@ -57,7 +57,7 @@ Notice that we use the predicate ``getType`` (available on all subclasses of ``E not expr.getAnOperand().isCompileTimeConstant() select expr -➤ `See this in the query console `__. Notice that fewer results are found. +➤ `See this in the query console on LGTM.com `__. Notice that fewer results are found. The class ``LoopStmt`` is a common superclass of all loops, including, in particular, ``for`` loops as in our example above. While different kinds of loops have different syntax, they all have a loop condition, which can be accessed through predicate ``getCondition``. We use the reflexive transitive closure operator ``*`` applied to the ``getAChildExpr`` predicate to express the requirement that ``expr`` should be nested inside the loop condition. In particular, it can be the loop condition itself. @@ -120,7 +120,7 @@ Now we rewrite our query to make use of these new classes: not expr.getAnOperand().isCompileTimeConstant() select expr -➤ `See the full query in the query console `__. +➤ `See the full query in the query console on LGTM.com `__. Further reading --------------- diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index 8948f388ed9..cba248fd276 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -68,7 +68,7 @@ For example, the following query finds all variables of type ``int`` in the prog pt.hasName("int") select v -➤ `See this in the query console `__. You're likely to get many results when you run this query because most projects contain many variables of type ``int``. +➤ `See this in the query console on LGTM.com `__. You're likely to get many results when you run this query because most projects contain many variables of type ``int``. Reference types are also categorized according to their declaration scope: @@ -85,7 +85,7 @@ For instance, this query finds all top-level types whose name is not the same as where tl.getName() != tl.getCompilationUnit().getName() select tl -➤ `See this in the query console `__. This pattern is seen in many projects. When we ran it on the LGTM.com demo projects, most of the projects had at least one instance of this problem in the source code. There were many more instances in the files referenced by the source code. +➤ `See this in the query console on LGTM.com `__. This pattern is seen in many projects. When we ran it on the LGTM.com demo projects, most of the projects had at least one instance of this problem in the source code. There were many more instances in the files referenced by the source code. Several more specialized classes are available as well: @@ -107,7 +107,7 @@ As an example, we can write a query that finds all nested classes that directly where nc.getASupertype() instanceof TypeObject select nc -➤ `See this in the query console `__. You're likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly. +➤ `See this in the query console on LGTM.com `__. You're likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly. Generics ~~~~~~~~ @@ -141,7 +141,7 @@ For instance, we could use the following query to find all parameterized instanc pt.getSourceDeclaration() = map select pt -➤ `See this in the query console `__. None of the LGTM.com demo projects contain parameterized instances of ``java.util.Map`` in their source code, but they all have results in reference files. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects contain parameterized instances of ``java.util.Map`` in their source code, but they all have results in reference files. In general, generic types may restrict which types a type parameter can be bound to. For instance, a type of maps from strings to numbers could be declared as follows: @@ -164,7 +164,7 @@ As an example, the following query finds all type variables with type bound ``Nu tb.getType().hasQualifiedName("java.lang", "Number") select tv -➤ `See this in the query console `__. When we ran it on the LGTM.com demo projects, the *neo4j/neo4j*, *gradle/gradle* and *hibernate/hibernate-orm* projects all contained examples of this pattern. +➤ `See this in the query console on LGTM.com `__. When we ran it on the LGTM.com demo projects, the *neo4j/neo4j*, *gradle/gradle* and *hibernate/hibernate-orm* projects all contained examples of this pattern. For dealing with legacy code that is unaware of generics, every generic type has a "raw" version without any type parameters. In the CodeQL libraries, raw types are represented using class ``RawType``, which has the expected subclasses ``RawClass`` and ``RawInterface``. Again, there is a predicate ``getSourceDeclaration`` for obtaining the corresponding generic type. As an example, we can find variables of (raw) type ``Map``: @@ -177,7 +177,7 @@ For dealing with legacy code that is unaware of generics, every generic type has rt.getSourceDeclaration().hasQualifiedName("java.util", "Map") select v -➤ `See this in the query console `__. Many projects have variables of raw type ``Map``. +➤ `See this in the query console on LGTM.com `__. Many projects have variables of raw type ``Map``. For example, in the following code snippet this query would find ``m1``, but not ``m2``: @@ -228,7 +228,7 @@ For example, the following query finds all expressions whose parents are ``retur where e.getParent() instanceof ReturnStmt select e -➤ `See this in the query console `__. Many projects have examples of ``return`` statements with child statements. +➤ `See this in the query console on LGTM.com `__. Many projects have examples of ``return`` statements with child statements. Therefore, if the program contains a return statement ``return x + y;``, this query will return ``x + y``. @@ -242,7 +242,7 @@ As another example, the following query finds statements whose parent is an ``if where s.getParent() instanceof IfStmt select s -➤ `See this in the query console `__. Many projects have examples of ``if`` statements with child statements. +➤ `See this in the query console on LGTM.com `__. Many projects have examples of ``if`` statements with child statements. This query will find both ``then`` branches and ``else`` branches of all ``if`` statements in the program. @@ -256,7 +256,7 @@ Finally, here is a query that finds method bodies: where s.getParent() instanceof Method select s -➤ `See this in the query console `__. Most projects have many method bodies. +➤ `See this in the query console on LGTM.com `__. Most projects have many method bodies. As these examples show, the parent node of an expression is not always an expression: it may also be a statement, for example, an ``IfStmt``. Similarly, the parent node of a statement is not always a statement: it may also be a method or a constructor. To capture this, the QL Java library provides two abstract class ``ExprParent`` and ``StmtParent``, the former representing any node that may be the parent node of an expression, and the latter any node that may be the parent node of a statement. @@ -276,7 +276,7 @@ For annotations, class ``Annotatable`` is a superclass of all program elements t from Constructor c select c.getAnAnnotation() -➤ `See this in the query console `__. The LGTM.com demo projects all use annotations, you can see examples where they are used to suppress warnings and mark code as deprecated. +➤ `See this in the query console on LGTM.com `__. The LGTM.com demo projects all use annotations, you can see examples where they are used to suppress warnings and mark code as deprecated. These annotations are represented by class ``Annotation``. An annotation is simply an expression whose type is an ``AnnotationType``. For example, you can amend this query so that it only reports deprecated constructors: @@ -290,7 +290,7 @@ These annotations are represented by class ``Annotation``. An annotation is simp anntp.hasQualifiedName("java.lang", "Deprecated") select ann -➤ `See this in the query console `__. Only constructors with the ``@deprecated`` annotation are reported this time. +➤ `See this in the query console on LGTM.com `__. Only constructors with the ``@deprecated`` annotation are reported this time. For more information on working with annotations, see the :doc:`article on annotations `. @@ -305,7 +305,7 @@ For Javadoc, class ``Element`` has a member predicate ``getDoc`` that returns a jdoc = f.getDoc().getJavadoc() select jdoc -➤ `See this in the query console `__. You can see this pattern in many projects. +➤ `See this in the query console on LGTM.com `__. You can see this pattern in many projects. Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocElement`` nodes, which can be traversed using member predicates ``getAChild`` and ``getParent``. For instance, you could edit the query so that it finds all ``@author`` tags in Javadoc comments on private fields: @@ -319,7 +319,7 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle at.getParent+() = jdoc select at -➤ `See this in the query console `__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields. .. pull-quote:: @@ -347,7 +347,7 @@ For example, the following query finds methods with a `cyclomatic complexity 40 select m -➤ `See this in the query console `__. Most large projects include some methods with a very high cyclomatic complexity. These methods are likely to be difficult to understand and test. +➤ `See this in the query console on LGTM.com `__. Most large projects include some methods with a very high cyclomatic complexity. These methods are likely to be difficult to understand and test. Call graph ---------- @@ -367,7 +367,7 @@ We can use predicate ``Call.getCallee`` to find out which method or constructor m.hasName("println") select c -➤ `See this in the query console `__. The LGTM.com demo projects all include many calls to methods of this name. +➤ `See this in the query console on LGTM.com `__. The LGTM.com demo projects all include many calls to methods of this name. Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So we can find methods and constructors that are never called using this query: @@ -379,7 +379,7 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So where not exists(c.getAReference()) select c -➤ `See this in the query console `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph `. +➤ `See this in the query console on LGTM.com `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph `. For more information about callables and calls, see the :doc:`article on the call graph `. diff --git a/docs/language/learn-ql/java/javadoc.rst b/docs/language/learn-ql/java/javadoc.rst index c484c480291..9b26d0c6aae 100644 --- a/docs/language/learn-ql/java/javadoc.rst +++ b/docs/language/learn-ql/java/javadoc.rst @@ -147,7 +147,7 @@ Now we can write a query for finding all callables ``c`` and ``@throws`` tags `` not mayThrow(c, exn) select tt, "Spurious @throws tag." -➤ `See this in the query console `__. This finds several results in the LGTM.com demo projects. +➤ `See this in the query console on LGTM.com `__. This finds several results in the LGTM.com demo projects. Improvements ~~~~~~~~~~~~ @@ -214,7 +214,7 @@ The first case can be covered by changing ``getDocumentedException`` to use the (result.hasName(tt.getExceptionName()) and visibleIn(tt.getFile(), result)) } -➤ `See this in the query console `__. This finds many fewer, more interesting results in the LGTM.com demo projects. +➤ `See this in the query console on LGTM.com `__. This finds many fewer, more interesting results in the LGTM.com demo projects. Currently, ``visibleIn`` only considers single-type imports, but you could extend it with support for other kinds of imports. diff --git a/docs/language/learn-ql/java/source-locations.rst b/docs/language/learn-ql/java/source-locations.rst index 23c7c89cb74..da8e8d26836 100644 --- a/docs/language/learn-ql/java/source-locations.rst +++ b/docs/language/learn-ql/java/source-locations.rst @@ -110,7 +110,7 @@ Here's a first version of our query: wsinner > wsouter select outer, "Whitespace around nested operators contradicts precedence." -➤ `See this in the query console `__. This query is likely to find results on most projects. +➤ `See this in the query console on LGTM.com `__. This query is likely to find results on most projects. The first conjunct of the ``where`` clause restricts ``inner`` to be an operand of ``outer``, the second conjunct binds ``wsinner`` and ``wsouter``, while the last conjunct selects the suspicious cases. @@ -141,7 +141,7 @@ Note that our predicate ``operatorWS`` computes the **total** amount of white sp wsinner > wsouter select outer, "Whitespace around nested operators contradicts precedence." -➤ `See this in the query console `__. Any results will be refined by our changes to the query. +➤ `See this in the query console on LGTM.com `__. Any results will be refined by our changes to the query. Another source of false positives are associative operators: in an expression of the form ``x + y+z``, the first plus is syntactically nested inside the second, since + in Java associates to the left; hence the expression is flagged as suspicious. But since + is associative to begin with, it does not matter which way around the operators are nested, so this is a false positive.To exclude these cases, let us define a new class identifying binary expressions with an associative operator: @@ -173,7 +173,7 @@ Now we can extend our query to discard results where the outer and the inner exp wsinner > wsouter select outer, "Whitespace around nested operators contradicts precedence." -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Notice that we again use ``getOp``, this time to determine whether two binary expressions have the same operator. Running our improved query now finds the Java standard library bug described in the Overview. It also flags up the following suspicious code in `Hadoop HBase `__: diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index 344e53f9951..ac65c539384 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -32,7 +32,7 @@ To determine ancestor types (including immediate super types, and also *their* s where B.hasName("B") select B.getASupertype+() -➤ `See this in the query console `__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``. +➤ `See this in the query console on LGTM.com `__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``. .. pull-quote:: @@ -78,7 +78,7 @@ This recipe is not too difficult to translate into a query: target.getElementType().(RefType).getASupertype+() = source.getElementType() select ce, "Potentially problematic array downcast." -➤ `See this in the query console `__. Many projects return results for this query. +➤ `See this in the query console on LGTM.com `__. Many projects return results for this query. Note that by casting ``target.getElementType()`` to a ``RefType``, we eliminate all cases where the element type is a primitive type, that is, ``target`` is an array of primitive type: the problem we are looking for cannot arise in that case. Unlike in Java, a cast in QL never fails: if an expression cannot be cast to the desired type, it is simply excluded from the query results, which is exactly what we want. @@ -141,7 +141,7 @@ Using these new classes we can extend our query to exclude calls to ``toArray`` not ce.getExpr().(CollectionToArrayCall).getActualReturnType() = target select ce, "Potentially problematic array downcast." -➤ `See this in the query console `__. Notice that fewer results are found by this improved query. +➤ `See this in the query console on LGTM.com `__. Notice that fewer results are found by this improved query. Example: Finding mismatched contains checks ------------------------------------------- @@ -267,7 +267,7 @@ Now we are ready to write a first version of our query: not haveCommonDescendant(collEltType, argType) select juccc, "Element type " + collEltType + " is incompatible with argument type " + argType -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Improvements ~~~~~~~~~~~~ @@ -294,7 +294,7 @@ Adding these three improvements, our final query becomes: not argType.hasName("") select juccc, "Element type " + collEltType + " is incompatible with argument type " + argType -➤ `See the full query in the query console `__. +➤ `See the full query in the query console on LGTM.com `__. Further reading --------------- diff --git a/docs/language/learn-ql/javascript/dataflow.rst b/docs/language/learn-ql/javascript/dataflow.rst index d8f2e2f2923..5762e2b2ba6 100644 --- a/docs/language/learn-ql/javascript/dataflow.rst +++ b/docs/language/learn-ql/javascript/dataflow.rst @@ -468,7 +468,7 @@ Further reading --------------- - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. - Learn about writing more precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis ` Answers diff --git a/docs/language/learn-ql/javascript/flow-labels.rst b/docs/language/learn-ql/javascript/flow-labels.rst index 3970a26058b..8e9881ce12d 100644 --- a/docs/language/learn-ql/javascript/flow-labels.rst +++ b/docs/language/learn-ql/javascript/flow-labels.rst @@ -400,4 +400,4 @@ Further reading - Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 0b161d32ec6..81da3135ec3 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -75,7 +75,7 @@ For example, the following query computes, for each folder, the number of JavaSc from Folder d select d.getRelativePath(), count(File f | f = d.getAFile() and f.getExtension() = "js") -➤ `See this in the query console `__. When you run the query on most projects, the results include folders that contain files with a ``js`` extension and folders that don't. +➤ `See this in the query console on LGTM.com `__. When you run the query on most projects, the results include folders that contain files with a ``js`` extension and folders that don't. Locations ^^^^^^^^^ @@ -136,7 +136,7 @@ As an example of a query operating entirely on the lexical level, consider the f where comma.getNextToken() instanceof CommaToken select comma, "Omitted array elements are bad style." -➤ `See this in the query console `__. If the query returns no results, this pattern isn't used in the projects that you analyzed. +➤ `See this in the query console on LGTM.com `__. If the query returns no results, this pattern isn't used in the projects that you analyzed. You can use predicate ``Locatable.getFirstToken()`` and ``Locatable.getLastToken()`` to access the first and last token (if any) belonging to an element with a source location. @@ -177,7 +177,7 @@ As an example of a query using only lexical information, consider the following from HtmlLineComment c select c, "Do not use HTML comments." -➤ `See this in the query console `__. When we ran this query on the *mozilla/pdf.js* project in LGTM.com, we found three HTML comments. +➤ `See this in the query console on LGTM.com `__. When we ran this query on the *mozilla/pdf.js* project in LGTM.com, we found three HTML comments. Syntactic level ~~~~~~~~~~~~~~~ @@ -349,7 +349,7 @@ As an example of how to use expression AST nodes, here is a query that finds exp where add = shift.getAnOperand() select add, "This expression should be bracketed to clarify precedence rules." -➤ `See this in the query console `__. When we ran this query on the *meteor/meteor* project in LGTM.com, we found many results where precedence could be clarified using brackets. +➤ `See this in the query console on LGTM.com `__. When we ran this query on the *meteor/meteor* project in LGTM.com, we found many results where precedence could be clarified using brackets. Functions ^^^^^^^^^ @@ -371,7 +371,7 @@ As an example, here is a query that finds all expression closures: where fe.getBody() instanceof Expr select fe, "Use arrow expressions instead of expression closures." -➤ `See this in the query console `__. None of the LGTM.com demo projects uses expression closures, but you may find this query gets results on other projects. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects uses expression closures, but you may find this query gets results on other projects. As another example, this query finds functions that have two parameters that bind the same variable: @@ -386,7 +386,7 @@ As another example, this query finds functions that have two parameters that bin p.getAVariable() = q.getAVariable() select fun, "This function has two parameters that bind the same variable." -➤ `See this in the query console `__. None of the LGTM.com demo projects has functions where two parameters bind the same variable. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects has functions where two parameters bind the same variable. Classes ^^^^^^^ @@ -442,7 +442,7 @@ Here is an example of a query to find declaration statements that declare the sa not ds.getTopLevel().isMinified() select ds, "Variable " + v.getName() + " is declared both $@ and $@.", d1, "here", d2, "here" -➤ `See this in the query console `__. This is not a common problem, so you may not find any results in your own projects. The *angular/angular.js* project on LGTM.com has one instance of this problem at the time of writing. +➤ `See this in the query console on LGTM.com `__. This is not a common problem, so you may not find any results in your own projects. The *angular/angular.js* project on LGTM.com has one instance of this problem at the time of writing. Notice the use of ``not ... isMinified()`` here and in the next few queries. This excludes any results found in minified code. If you delete ``and not ds.getTopLevel().isMinified()`` and re-run the query, two results in minified code in the *meteor/meteor* project are reported. @@ -469,7 +469,7 @@ As an example of a query involving properties, consider the following query that not oe.getTopLevel().isMinified() select oe, "Property " + p1.getName() + " is defined both $@ and $@.", p1, "here", p2, "here" -➤ `See this in the query console `__. Many projects have a few instances of object expressions with two identically named properties. +➤ `See this in the query console on LGTM.com `__. Many projects have a few instances of object expressions with two identically named properties. Modules ^^^^^^^ @@ -535,7 +535,7 @@ As an example, consider the following query which finds distinct function declar not g.getTopLevel().isMinified() select f, g -➤ `See this in the query console `__. Some projects declare conflicting functions of the same name and rely on platform-specific behavior to disambiguate the two declarations. +➤ `See this in the query console on LGTM.com `__. Some projects declare conflicting functions of the same name and rely on platform-specific behavior to disambiguate the two declarations. Control flow ~~~~~~~~~~~~ @@ -572,7 +572,7 @@ As an example of an analysis using basic blocks, ``BasicBlock.isLiveAtEntry(v, u not f.getStartBB().isLiveAtEntry(gv, _) select f, "This function uses " + gv + " like a local variable." -➤ `See this in the query console `__. Many projects have some variables which look as if they were intended to be local. +➤ `See this in the query console on LGTM.com `__. Many projects have some variables which look as if they were intended to be local. Data flow ~~~~~~~~~ @@ -597,7 +597,7 @@ As an example, the following query finds definitions of local variables that are not exists (VarUse use | def = use.getADef()) select def, "Dead store of local variable." -➤ `See this in the query console `__. Many projects have some examples of useless assignments to local variables. +➤ `See this in the query console on LGTM.com `__. Many projects have some examples of useless assignments to local variables. SSA ^^^ @@ -640,7 +640,7 @@ For example, here is a query that finds all invocations of a method called ``sen send.getMethodName() = "send" select send -➤ `See this in the query console `__. The query finds HTTP response sends in the `AMP HTML `__ project. +➤ `See this in the query console on LGTM.com `__. The query finds HTTP response sends in the `AMP HTML `__ project. Note that the data flow modeling in this library is intraprocedural, that is, flow across function calls and returns is *not* modeled. Likewise, flow through object properties and global variables is not modeled. @@ -705,7 +705,7 @@ As an example of a call-graph-based query, here is a query to find invocations f not exists(invk.getACallee()) select invk, "Unable to find a callee for this invocation." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Inter-procedural data flow ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -841,7 +841,7 @@ As an example of the use of these classes, here is a query that counts for every from NodeModule m select m, count(m.getAnImportedModule()) -➤ `See this in the query console `__. When you analyze a project, for each module you can see how many other modules it imports. +➤ `See this in the query console on LGTM.com `__. When you analyze a project, for each module you can see how many other modules it imports. NPM ^^^ @@ -870,7 +870,7 @@ As an example of the use of these classes, here is a query that identifies unuse not exists (Require req | req.getTopLevel() = pkg.getAModule() | name = req.getImportedPath().getValue()) select deps, "Unused dependency '" + name + "'." -➤ `See this in the query console `__. It is not uncommon for projects to have some unused dependencies. +➤ `See this in the query console on LGTM.com `__. It is not uncommon for projects to have some unused dependencies. React ^^^^^ @@ -897,7 +897,7 @@ For example, here is a query to find SQL queries that use string concatenation ( where ss instanceof AddExpr select ss, "Use templating instead of string concatenation." -➤ `See this in the query console `__, showing two (benign) results on `strong-arc `__. +➤ `See this in the query console on LGTM.com `__, showing two (benign) results on `strong-arc `__. Miscellaneous ~~~~~~~~~~~~~ @@ -963,7 +963,7 @@ As an example, here is a query that finds ``@param`` tags that do not specify th not exists(t.getName()) select t, "@param tag is missing name." -➤ `See this in the query console `__. Of the LGTM.com demo projects analyzed, only *Semantic-Org/Semantic-UI* has an example where the ``@param`` tag omits the name. +➤ `See this in the query console on LGTM.com `__. Of the LGTM.com demo projects analyzed, only *Semantic-Org/Semantic-UI* has an example where the ``@param`` tag omits the name. For full details on these and other classes representing JSDoc comments and type expressions, see `the API documentation `__. @@ -1033,4 +1033,4 @@ Further reading - Learn about the standard CodeQL libraries used to write queries for TypeScript in :doc:`CodeQL libraries for TypeScript `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index d6cca17749d..6c9cf96bc59 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -121,7 +121,7 @@ Select expressions that cast a value to a type parameter: where assertion.getTypeAnnotation() = param.getLocalTypeName().getAnAccess() select assertion, "Cast to type parameter." -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Classes and interfaces ~~~~~~~~~~~~~~~~~~~~~~ @@ -407,7 +407,7 @@ It is best to use `TypeName `__. +➤ `See this in the query console on LGTM.com `__. Find imported names that are used as both a type and a value: @@ -420,7 +420,7 @@ Find imported names that are used as both a type and a value: and exists (VarAccess access | access.getVariable().getADeclaration() = spec.getLocal()) select spec, "Used as both variable and type" -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Namespace names ~~~~~~~~~~~~~~~ @@ -451,4 +451,4 @@ Further reading - Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index 473521a9b0f..1e73be413c7 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -522,5 +522,5 @@ Further reading --------------- - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. - Learn about writing precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis `. diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index d1645315784..9291f4dc907 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -45,7 +45,7 @@ Example finding unreachable AST nodes where not exists(node.getAFlowNode()) select node -➤ `See this in the query console `__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements. +➤ `See this in the query console on LGTM.com `__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements. Example finding unreachable statements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +58,7 @@ Example finding unreachable statements where not exists(s.getAFlowNode()) select s -➤ `See this in the query console `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard "Unreachable code" query. For more information, see `Unreachable code `__ on LGTM.com. +➤ `See this in the query console on LGTM.com `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard "Unreachable code" query. For more information, see `Unreachable code `__ on LGTM.com. The ``BasicBlock`` class ------------------------ @@ -112,7 +112,7 @@ Example finding mutually exclusive blocks within the same function ) select b1, b2 -➤ `See this in the query console `__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis. For more information, see :doc:`Analyzing data flow and tracking tainted data in Python `. +➤ `See this in the query console on LGTM.com `__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis. For more information, see :doc:`Analyzing data flow and tracking tainted data in Python `. Further reading --------------- diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index 8fa89f5e188..20e47267825 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -26,7 +26,7 @@ Using the member predicate ``Function.getName()``, we can list all of the getter where f.getName().matches("get%") select f, "This is a function called get..." -➤ `See this in the query console `__. This query typically finds a large number of results. Usually, many of these results are for functions (rather than methods) which we are not interested in. +➤ `See this in the query console on LGTM.com `__. This query typically finds a large number of results. Usually, many of these results are for functions (rather than methods) which we are not interested in. Finding all methods called "get..." ----------------------------------- @@ -41,7 +41,7 @@ You can modify the query above to return more interesting results. As we are onl where f.getName().matches("get%") and f.isMethod() select f, "This is a method called get..." -➤ `See this in the query console `__. This finds methods whose name starts with ``"get"``, but many of those are not the sort of simple getters we are interested in. +➤ `See this in the query console on LGTM.com `__. This finds methods whose name starts with ``"get"``, but many of those are not the sort of simple getters we are interested in. Finding one line methods called "get..." ---------------------------------------- @@ -57,7 +57,7 @@ We can modify the query further to include only methods whose body consists of a and count(f.getAStmt()) = 1 select f, "This function is (probably) a getter." -➤ `See this in the query console `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Expressions and statements in Python `." +➤ `See this in the query console on LGTM.com `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Expressions and statements in Python `." Finding a call to a specific function ------------------------------------- @@ -72,7 +72,7 @@ This query uses ``Call`` and ``Name`` to find calls to the function ``eval`` - w where call.getFunc() = name and name.getId() = "eval" select call, "call to 'eval'." -➤ `See this in the query console `__. Some of the demo projects on LGTM.com use this function. +➤ `See this in the query console on LGTM.com `__. Some of the demo projects on LGTM.com use this function. The ``Call`` class represents calls in Python. The ``Call.getFunc()`` predicate gets the expression being called. ``Name.getId()`` gets the identifier (as a string) of the ``Name`` expression. Due to the dynamic nature of Python, this query will select any call of the form ``eval(...)`` regardless of whether it is a call to the built-in function ``eval`` or not. diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index c7809eb710b..d124277d0b5 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -47,7 +47,7 @@ All scopes are basically a list of statements, although ``Scope`` classes have a where f.getScope() instanceof Function select f -➤ `See this in the query console `__. Many projects have nested functions. +➤ `See this in the query console on LGTM.com `__. Many projects have nested functions. Statement ^^^^^^^^^ @@ -89,7 +89,7 @@ As an example, to find expressions of the form ``a+2`` where the left is a simpl where bin.getLeft() instanceof Name and bin.getRight() instanceof Num select bin -➤ `See this in the query console `__. Many projects include examples of this pattern. +➤ `See this in the query console on LGTM.com `__. Many projects include examples of this pattern. Variable ^^^^^^^^ @@ -120,7 +120,7 @@ For our first example, we can find all ``finally`` blocks by using the ``Try`` c from Try t select t.getFinalbody() -➤ `See this in the query console `__. Many projects include examples of this pattern. +➤ `See this in the query console on LGTM.com `__. Many projects include examples of this pattern. 2. Finding ``except`` blocks that do nothing '''''''''''''''''''''''''''''''''''''''''''' @@ -151,7 +151,7 @@ Both forms are equivalent. Using the positive expression, the whole query looks where forall(Stmt s | s = ex.getAStmt() | s instanceof Pass) select ex -➤ `See this in the query console `__. Many projects include pass-only ``except`` blocks. +➤ `See this in the query console on LGTM.com `__. Many projects include pass-only ``except`` blocks. Summary ^^^^^^^ @@ -272,7 +272,7 @@ Using this predicate we can select the longest ``BasicBlock`` by selecting the ` where bb_length(b) = max(bb_length(_)) select b -➤ `See this in the query console `__. When we ran it on the LGTM.com demo projects, the *openstack/nova* and *ytdl-org/youtube-dl* projects both contained source code results for this query. +➤ `See this in the query console on LGTM.com `__. When we ran it on the LGTM.com demo projects, the *openstack/nova* and *ytdl-org/youtube-dl* projects both contained source code results for this query. .. pull-quote:: @@ -309,7 +309,7 @@ For example, which ``ClassValue``\ s are iterable can be determined using the qu where cls.hasAttribute("__iter__") select cls -➤ `See this in the query console `__ This query returns a list of classes for the projects analyzed. If you want to include the results for ``builtin`` classes, which do not have any Python source code, show the non-source results. For more information, see `builtin classes `__ in the Python documentation. +➤ `See this in the query console on LGTM.com `__ This query returns a list of classes for the projects analyzed. If you want to include the results for ``builtin`` classes, which do not have any Python source code, show the non-source results. For more information, see `builtin classes `__ in the Python documentation. Summary ^^^^^^^ diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index 40f2ecb81ff..8fbde0d9b35 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -74,7 +74,7 @@ First we can write a query to find ordered pairs of ``except`` blocks for a ``tr ) select t, ex1, ex2 -➤ `See this in the query console `__. Many projects contain ordered ``except`` blocks in a ``try`` statement. +➤ `See this in the query console on LGTM.com `__. Many projects contain ordered ``except`` blocks in a ``try`` statement. Here ``ex1`` and ``ex2`` are both ``except`` handlers in the ``try`` statement ``t``. By using the indices ``i`` and ``j`` we can also ensure that ``ex1`` precedes ``ex2``. @@ -121,7 +121,7 @@ Combining the parts of the query we get this: ) select t, ex1, ex2 -➤ `See this in the query console `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard "Unreachable 'except' block" query. For more information, see `Unreachable 'except' block `__ on LGTM.com. +➤ `See this in the query console on LGTM.com `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard "Unreachable 'except' block" query. For more information, see `Unreachable 'except' block `__ on LGTM.com. .. pull-quote:: @@ -156,7 +156,7 @@ Then we need to determine if the object ``iter`` is iterable. We can test ``Clas not exists(cls.lookup("__iter__")) select loop, cls -➤ `See this in the query console `__. Many projects use a non-iterable as a loop iterator. +➤ `See this in the query console on LGTM.com `__. Many projects use a non-iterable as a loop iterator. Many of the results shown will have ``cls`` as ``NoneType``. It is more informative to show where these ``None`` values may come from. To do this we use the final field of ``pointsTo``, as follows: @@ -172,7 +172,7 @@ Many of the results shown will have ``cls`` as ``NoneType``. It is more informat not cls.hasAttribute("__iter__") select loop, cls, origin -➤ `See this in the query console `__. This reports the same results, but with a third column showing the source of the ``None`` values. +➤ `See this in the query console on LGTM.com `__. This reports the same results, but with a third column showing the source of the ``None`` values. Finding calls using call-graph analysis ---------------------------------------------------- @@ -193,7 +193,7 @@ The original query looked this: where call.getFunc() = name and name.getId() = "eval" select call, "call to 'eval'." -➤ `See this in the query console `__. Some of the demo projects on LGTM.com have calls that match this pattern. +➤ `See this in the query console on LGTM.com `__. Some of the demo projects on LGTM.com have calls that match this pattern. There are two problems with this query: @@ -221,7 +221,7 @@ Then we can use ``Value.getACall()`` to identify calls to the ``eval`` function, call = eval.getACall() select call, "call to 'eval'." -➤ `See this in the query console `__. This accurately identifies calls to the builtin ``eval`` function even when they are referred to using an alternative name. Any false positive results with calls to other ``eval`` functions, reported by the original query, have been eliminated. +➤ `See this in the query console on LGTM.com `__. This accurately identifies calls to the builtin ``eval`` function even when they are referred to using an alternative name. Any false positive results with calls to other ``eval`` functions, reported by the original query, have been eliminated. Further reading --------------- diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index eda2d1e4578..9e817d5c5c6 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -52,7 +52,7 @@ The ``global`` statement in Python declares a variable with a global (module-lev where g.getScope() instanceof Module select g -➤ `See this in the query console `__. None of the demo projects on LGTM.com has a global statement that matches this pattern. +➤ `See this in the query console on LGTM.com `__. None of the demo projects on LGTM.com has a global statement that matches this pattern. The line: ``g.getScope() instanceof Module`` ensures that the ``Scope`` of ``Global g`` is a ``Module``, rather than a class or function. @@ -79,7 +79,7 @@ To find statements like this that could be simplified we can write a query. and forall(Stmt p | p = l.getAnItem() | p instanceof Pass) select i -➤ `See this in the query console `__. Many projects have some ``if`` statements that match this pattern. +➤ `See this in the query console on LGTM.com `__. Many projects have some ``if`` statements that match this pattern. The line: ``(l = i.getBody() or l = i.getOrelse())`` restricts the ``StmtList l`` to branches of the ``if`` statement. @@ -148,7 +148,7 @@ We can check for these using a query. and cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal select cmp -➤ `See this in the query console `__. Two of the demo projects on LGTM.com use this pattern: *saltstack/salt* and *openstack/nova*. +➤ `See this in the query console on LGTM.com `__. Two of the demo projects on LGTM.com use this pattern: *saltstack/salt* and *openstack/nova*. The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` checks that the first comparison operator is "is" and that the first comparator is a literal. @@ -178,7 +178,7 @@ If there are duplicate keys in a Python dictionary, then the second key will ove and k1 != k2 and same_key(k1, k2) select k1, "Duplicate key in dict literal" -➤ `See this in the query console `__. When we ran this query on LGTM.com, the source code of the *saltstack/salt* project contained an example of duplicate dictionary keys. The results were also highlighted as alerts by the standard "Duplicate key in dict literal" query. Two of the other demo projects on LGTM.com refer to duplicate dictionary keys in library files. For more information, see `Duplicate key in dict literal `__ on LGTM.com. +➤ `See this in the query console on LGTM.com `__. When we ran this query on LGTM.com, the source code of the *saltstack/salt* project contained an example of duplicate dictionary keys. The results were also highlighted as alerts by the standard "Duplicate key in dict literal" query. Two of the other demo projects on LGTM.com refer to duplicate dictionary keys in library files. For more information, see `Duplicate key in dict literal `__ on LGTM.com. The supporting predicate ``same_key`` checks that the keys have the same identifier. Separating this part of the logic into a supporting predicate, instead of directly including it in the query, makes it easier to understand the query as a whole. The casts defined in the predicate restrict the expression to the type specified and allow predicates to be called on the type that is cast-to. For example: @@ -220,7 +220,7 @@ This basic query can be improved by checking that the one line of code is a Java and attr.getObject() = self and self.getId() = "self" select f, "This function is a Java-style getter." -➤ `See this in the query console `__. Of the demo projects on LGTM.com, only the *openstack/nova* project has examples of functions that appear to be Java-style getters. +➤ `See this in the query console on LGTM.com `__. Of the demo projects on LGTM.com, only the *openstack/nova* project has examples of functions that appear to be Java-style getters. .. code-block:: ql diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index d1e4ebcf140..687b250b42c 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -55,7 +55,7 @@ Query metadata is used to identify your custom queries when they are added to th - If you are contributing a query to the GitHub repository, please read the `query metadata style guide `__. - If you are adding a custom query to a query pack for analysis using LGTM , see `Writing custom queries to include in LGTM analysis `__. - If you are analyzing a database using the `CodeQL CLI `__, your query metadata must contain ``@kind``. -- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. For more information, `Using the query console `__ and `Using the extension `__. +- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. For more information, see `Using the query console `__ on LGTM.com.and `Using the extension `__ in the CodeQL for VS Code help. .. pull-quote:: From 0771c392940e3a9b0ba8b0c4b43a6f0729cb19d8 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 1 Apr 2020 15:21:11 +0100 Subject: [PATCH 244/459] Update docs/language/ql-handbook/about-the-ql-language.rst Co-Authored-By: Felicity Chapman --- docs/language/ql-handbook/about-the-ql-language.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/ql-handbook/about-the-ql-language.rst b/docs/language/ql-handbook/about-the-ql-language.rst index 72e6209f2e6..e5e03e5bb07 100644 --- a/docs/language/ql-handbook/about-the-ql-language.rst +++ b/docs/language/ql-handbook/about-the-ql-language.rst @@ -62,9 +62,9 @@ Here are a few prominent conceptual and functional differences between general p Further reading --------------- -Academic references available from the `Semmle website `__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: +`Academic references `__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: - `Database theory: Query languages `__ - `Logic Programming and Databases book - Amazon page `__ - `Foundations of Databases `__ -- `Datalog `__ \ No newline at end of file +- `Datalog `__ From 500f49d565e7c3f652d69c317da67c5c85f8bdfd Mon Sep 17 00:00:00 2001 From: james Date: Wed, 1 Apr 2020 15:22:42 +0100 Subject: [PATCH 245/459] docs: fix a few more links --- docs/language/learn-ql/database.rst | 2 +- docs/language/learn-ql/introduction-to-ql.rst | 2 +- .../learn-ql/writing-queries/introduction-to-queries.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/database.rst b/docs/language/learn-ql/database.rst index fe8e2e273ef..369b1d73fb0 100644 --- a/docs/language/learn-ql/database.rst +++ b/docs/language/learn-ql/database.rst @@ -1,7 +1,7 @@ What's in a CodeQL database? ============================ -A CodeQL database contains a variety of data related to a particular code base at a particular point in time. For details of how the database is generated see `Database generation `__. +A CodeQL database contains a variety of data related to a particular code base at a particular point in time. For details of how the database is generated see `Database generation `__ on LGTM.com. The database contains a full, hierarchical representation of the program defined by the code base. The database schema varies according to the language analyzed. The schema provides an interface between the initial lexical analysis during the extraction process, and the actual complex analysis using CodeQL. When the source code languages being analyzed change (such as Java 7 evolving into Java 8), this interface between the analysis phases can also change. diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index c80785235f5..026d4d8bbf2 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -115,7 +115,7 @@ To simplify the query, we can introduce a class ``SmallInt`` representing the in ➤ `See this in the query console on LGTM.com `__ Now that you've seen some general examples, let's use the CodeQL libraries to analyze projects. -In particular, LGTM generates a database representing the code and then CodeQL is used to query this database. See `Database generation `__ for more details on how the database is built. +In particular, LGTM generates a database representing the code and then CodeQL is used to query this database. For more information, ee `Database generation `__ on LGTM.com. .. XX: Perhaps a link to the "CodeQL libraries for X"? diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index 687b250b42c..c6f30b8075b 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -55,7 +55,7 @@ Query metadata is used to identify your custom queries when they are added to th - If you are contributing a query to the GitHub repository, please read the `query metadata style guide `__. - If you are adding a custom query to a query pack for analysis using LGTM , see `Writing custom queries to include in LGTM analysis `__. - If you are analyzing a database using the `CodeQL CLI `__, your query metadata must contain ``@kind``. -- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. For more information, see `Using the query console `__ on LGTM.com.and `Using the extension `__ in the CodeQL for VS Code help. +- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. For more information, see `Using the query console `__ on LGTM.com and `Using the extension `__ in the CodeQL for VS Code help. .. pull-quote:: From e246b6b9e349e438328341775ae9c4733726c581 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 1 Apr 2020 15:26:03 +0100 Subject: [PATCH 246/459] Move links into different section --- docs/language/ql-handbook/about-the-ql-language.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/language/ql-handbook/about-the-ql-language.rst b/docs/language/ql-handbook/about-the-ql-language.rst index e5e03e5bb07..8cb38d05df3 100644 --- a/docs/language/ql-handbook/about-the-ql-language.rst +++ b/docs/language/ql-handbook/about-the-ql-language.rst @@ -3,11 +3,6 @@ About the QL language QL is the powerful query language that underlies CodeQL, which is used to analyze code. -For more information about the important concepts and syntactic constructs of QL, see the individual reference topics such as :doc:`Predicates ` and :doc:`Types `. -The explanations and examples help you understand how the language works, and how to write more advanced QL code. - -For formal specifications of the QL language and QLDoc comments, see the :doc:`QL language specification ` and :doc:`QLDoc comment specification `. - About query languages and databases ----------------------------------- @@ -44,6 +39,11 @@ When you write this process in QL, it closely resembles the above structure. Not result = count(getADescendant(p)) } +For more information about the important concepts and syntactic constructs of QL, see the individual reference topics such as :doc:`Expressions ` and :doc:`Recursion `. +The explanations and examples help you understand how the language works, and how to write more advanced QL code. + +For formal specifications of the QL language and QLDoc comments, see the :doc:`QL language specification ` and :doc:`QLDoc comment specification `. + QL and object orientation ------------------------- From 4d9cc8b3e04436542861d41127e11b3d4bf83983 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 1 Apr 2020 15:31:04 +0100 Subject: [PATCH 247/459] docs: small change to query metadata table --- .../writing-queries/query-metadata.rst | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/language/learn-ql/writing-queries/query-metadata.rst b/docs/language/learn-ql/writing-queries/query-metadata.rst index 5d669a25389..362b3c54405 100644 --- a/docs/language/learn-ql/writing-queries/query-metadata.rst +++ b/docs/language/learn-ql/writing-queries/query-metadata.rst @@ -22,24 +22,24 @@ Core properties The following properties are supported by all query files: -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Property | Value | Description | -+=======================+===========================+=============================================================================================================================================================================================================================================================================================================================================================================================================================================================================+ -| ``@description`` | ```` | A sentence or short paragraph to describe the purpose of the query and *why* the result is useful or important. The description is written in plain text, and uses single quotes (``'``) to enclose code elements. | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@id`` | ```` | A sequence of words composed of lowercase letters or digits, delimited by ``/`` or ``-``, identifying and classifying the query. Each query must have a **unique** ID. To ensure this, it may be helpful to use a fixed structure for each ID. For example, the standard LGTM queries have the following format: ``/``. | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@kind`` | | ``problem`` | Identifies the query is an alert (``@kind problem``), a path (``@kind path-problem``), or a metric (``@kind metric``). For further information on these query types, see :doc:`About CodeQL queries ` | -| | | ``path-problem`` | | -| | | ``metric`` | | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@name`` | ```` | A statement that defines the label of the query. The name is written in plain text, and uses single quotes (``'``) to enclose code elements. | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@tags`` | | ``correctness`` | These tags group queries together in broad categories to make it easier to search for them and identify them. You can also `filter alerts `__ based on their tags. In addition to the common tags listed here, there are also a number of more specific categories. For more information about some of the tags that are already used and what they mean, see `Query tags `__. | -| | | ``mantainability`` | | -| | | ``readability`` | | -| | | ``security`` | | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Property | Value | Description | ++=======================+===========================+==============================================================================================================================================================================================================================================================================================================================================================================+ +| ``@description`` | ```` | A sentence or short paragraph to describe the purpose of the query and *why* the result is useful or important. The description is written in plain text, and uses single quotes (``'``) to enclose code elements. | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@id`` | ```` | A sequence of words composed of lowercase letters or digits, delimited by ``/`` or ``-``, identifying and classifying the query. Each query must have a **unique** ID. To ensure this, it may be helpful to use a fixed structure for each ID. For example, the standard LGTM queries have the following format: ``/``. | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@kind`` | | ``problem`` | Identifies the query is an alert (``@kind problem``), a path (``@kind path-problem``), or a metric (``@kind metric``). For further information on these query types, see :doc:`About CodeQL queries `. | +| | | ``path-problem`` | | +| | | ``metric`` | | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@name`` | ```` | A statement that defines the label of the query. The name is written in plain text, and uses single quotes (``'``) to enclose code elements. | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@tags`` | | ``correctness`` | These tags group queries together in broad categories to make it easier to search for them and identify them. In addition to the common tags listed here, there are also a number of more specific categories. For more information about some of the tags that are already used and what they mean, see `Query tags `__ on LGTM.com. | +| | | ``mantainability`` | | +| | | ``readability`` | | +| | | ``security`` | | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Additional properties for problem and path-problem queries From a514cecdf4967393862af83ee014e5c144158098 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 1 Apr 2020 15:44:07 +0100 Subject: [PATCH 248/459] Fix sidebar title --- docs/language/ql-handbook/conf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/language/ql-handbook/conf.py b/docs/language/ql-handbook/conf.py index 1b4887c0f06..d1febd209b5 100644 --- a/docs/language/ql-handbook/conf.py +++ b/docs/language/ql-handbook/conf.py @@ -41,7 +41,7 @@ highlight_language = 'ql' master_doc = 'index' # Project-specific information. -project = u'QL language handbook' +project = u'QL language reference' # The version info for this project, if different from version and release in main conf.py file. # The short X.Y version. @@ -53,10 +53,10 @@ project = u'QL language handbook' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -html_title = 'QL language handbook' +html_title = 'QL language reference' # Output file base name for HTML help builder. -htmlhelp_basename = 'QL language handbook' +htmlhelp_basename = 'QL language reference' # -- Currently unused, but potentially useful, configs-------------------------------------- From aea295757029d6b5c5969f282558f1f2da7f8b2c Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 1 Apr 2020 16:09:04 +0100 Subject: [PATCH 249/459] Update docs/language/learn-ql/java/dataflow.rst Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/java/dataflow.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index 13aebe178f6..ba0b6032dbc 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -258,7 +258,7 @@ Further reading - Try the worked examples in these articles: :doc:`Navigating the call graph ` and :doc:`Working with source locations `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console on LGTM.com `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. Answers ------- From 1ba7a4d39b8e9807829cb2aac1adf01bd5a5cc05 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 1 Apr 2020 16:09:28 +0100 Subject: [PATCH 250/459] Update docs/language/learn-ql/introduction-to-ql.rst Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/introduction-to-ql.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index 026d4d8bbf2..709f10b7120 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -115,7 +115,7 @@ To simplify the query, we can introduce a class ``SmallInt`` representing the in ➤ `See this in the query console on LGTM.com `__ Now that you've seen some general examples, let's use the CodeQL libraries to analyze projects. -In particular, LGTM generates a database representing the code and then CodeQL is used to query this database. For more information, ee `Database generation `__ on LGTM.com. +In particular, LGTM generates a database representing the code and then CodeQL is used to query this database. For more information, see `Database generation `__ on LGTM.com. .. XX: Perhaps a link to the "CodeQL libraries for X"? From e83bee2f0273915759da8ec1b95416e97917363f Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 1 Apr 2020 16:42:49 +0100 Subject: [PATCH 251/459] Copy Go docs into this repo --- docs/language/learn-ql/go/ast.dot | 22 + docs/language/learn-ql/go/ast.png | Bin 0 -> 46453 bytes docs/language/learn-ql/go/cfg.dot | 8 + docs/language/learn-ql/go/cfg.png | Bin 0 -> 45148 bytes docs/language/learn-ql/go/cfg2.dot | 14 + docs/language/learn-ql/go/cfg2.png | Bin 0 -> 65430 bytes docs/language/learn-ql/go/dfg.dot | 11 + docs/language/learn-ql/go/dfg.png | Bin 0 -> 34931 bytes .../learn-ql/go/introduce-libraries-go.rst | 621 ++++++++++++++++++ docs/language/learn-ql/go/ql-for-go.rst | 9 +- docs/language/learn-ql/go/ssa.dot | 15 + docs/language/learn-ql/go/ssa.png | Bin 0 -> 68479 bytes 12 files changed, 699 insertions(+), 1 deletion(-) create mode 100644 docs/language/learn-ql/go/ast.dot create mode 100644 docs/language/learn-ql/go/ast.png create mode 100644 docs/language/learn-ql/go/cfg.dot create mode 100644 docs/language/learn-ql/go/cfg.png create mode 100644 docs/language/learn-ql/go/cfg2.dot create mode 100644 docs/language/learn-ql/go/cfg2.png create mode 100644 docs/language/learn-ql/go/dfg.dot create mode 100644 docs/language/learn-ql/go/dfg.png create mode 100644 docs/language/learn-ql/go/introduce-libraries-go.rst create mode 100644 docs/language/learn-ql/go/ssa.dot create mode 100644 docs/language/learn-ql/go/ssa.png diff --git a/docs/language/learn-ql/go/ast.dot b/docs/language/learn-ql/go/ast.dot new file mode 100644 index 00000000000..fbf32b744ed --- /dev/null +++ b/docs/language/learn-ql/go/ast.dot @@ -0,0 +1,22 @@ +digraph ast { + graph [dpi=300]; + "x" [shape=rect]; + "y" [shape=rect]; + "x + y" [shape=rect]; + "(x + y)" [shape=rect]; + "z" [shape=rect]; + "(x + y) * z" [shape=rect]; + invis1 [style=invis]; + invis2 [style=invis]; + invis3 [style=invis]; + + "(x + y) * z" -> "(x + y)" [label=" 0"]; + "(x + y) * z" -> "z" [label=" 1"]; + "(x + y)" -> "x + y" [label=" 0"]; + "x + y" -> "x" [label=" 0"]; + "x + y" -> "y" [label=" 1"]; + + "z" -> invis1 [style=invis]; + invis1 -> invis2 [style=invis]; + invis1 -> invis3 [style=invis]; +} diff --git a/docs/language/learn-ql/go/ast.png b/docs/language/learn-ql/go/ast.png new file mode 100644 index 0000000000000000000000000000000000000000..61a9f29b80afb4b58546da8bfecd05c30618acb1 GIT binary patch literal 46453 zcmeFZc|6za-ah(mUJbM=noJEUv&fW86-gzM%tMj6h$u77R3afHLn`w;CPNbnQRZZd z%pru#=ej@k+I#KaeqQIC=bY#Kb6!9Dwb!!h^Zk79;XPc}^?u*Cr}A-mx)qyO&}cL| zg~PHcG}_`;{D1t9rT7yW)72;OucZb@|N{22bUyHx^#GE^}a^xvt~18h3G1t(VM!KRn%c zFz(;a;CD)m(h{yH_oM84LD4XtisHQ?Z@V4`Rk+Bto0Z3n zmluDtd7-lqqruPVTRLo2%jbW0@4dT_e*V|wHA|T1e>=T>h1mRWuMRO>_{W1@9If-e z(U?xWS}^~s$P@QP^S_;wU9fEaw|bBNyDywRhL42Dt0n5h{P=OMN`MxA;9YU?qkDKy z$$K*1=Lcyt<@NXP-`C2%5Ye-dro8oc1`Exdi~FIx@;^rKx3RSCX{FI>4wVM**2JFT zCa-H89v)72nYx7EY3>h|G3r>a=x7efsUK<24QVnjW~N%^)TYMz6^rqedT+Kz&(Fa9 ze}1a}<7@Z7Ur6@qzh{43SKhoiAUQWZGFhrWYaqUYOIb@R_(^1>-R!hO)rlkhUrfSI z9X{;Q?AXU!bpmhak|b`hYM*Vl&%nz;sgEIhPtHt^?qONR*j>JFu)4&byXM736C)#| zpnE3`y2>9{jZ{b{os2r(6B8BcTh$}P0v`)kiG+*13ip)xydx@G?Jy)EZsBp6sU%%>)l`E@m(lObNH(l<#FVFfpE-Bw!ywa{F zNnf9CvyczFutn{$42wFEkUuae8#1Wyt9u_G_u91QP*UDla6^_=l9JSf>}YSz9+s6$ zYhq5yv$_6`uq>FlBsuZ@L9l?~&7Q-)iOwS5lqL%KUAHRaOmseS8y1%LW*v3h3HOR6 zZtuQg{knCLmzy2ry_iI6u|SNQH=B#E<+{?^dfH|9!>*j6A}0U9!05YoR~c%SKi(JR zG?=H3udI6Kx$cy*a_dlVT%mUHJr>FQ%*%s%c73&qUYmt0udS9cb<)Fkl-#4f<5$}q ze)IB>y}nQJo*OrA1kqhT^6W(9p(96+J}B*|yuN(huZgZOrVj#_2XxLiW}m>;oHRF& zJ><2y!&+1a{=P%ua-;PvqkOkH*U|p3>e^YB{_MP(sZWov>_%8Qy^L%-*ZUm1zF$$& zGYY;!uG98(8+X6Duub(4mNyJ9dUo~dLa&Vi2X-li#{XO;rzGrxzhGRqZu`U1j!<3R zR?ECmwecU_pCfbTW~c00Uo9w|stA*|GSnio@TO*QVW4rZ7t201zK2Km@82IRZWr5g zIQpHQ>x9w7)Re{C?96RX&zPTm-grdP@mF$Lv+LCP9qjDcb&A14_t}Ll8#OBZeb2YP zx-!}M$ckt1VXmWb`aMI%Y<2Q%E>Ax`5{*+!&|(Z`gMFnA?P0-8do2rZ zGX@J=1UNko3^d)X*fG>DzhQ?N_T#3n>Typ`Pe-iU4h3(i$>_=P!K6o)IWY(JT)%aT zTS7v|_t)Fi(x&|l86@_LUml28*K?5bO*g4vrDG9S{TM7oC&jE%4|Pc9})OUfH)g`OLu^*RO9pz8If-L2~8k$U1$urqqGD zq_7C~=-aM3uNWB^x(hex3k7t1iZ~c7Y8C1@_9I4mcF5atv_^f0LWR^+{PSZ$PnNOT z%M9j?hu&k}YrwM|h{8w?Y1Uow(qMA}Bez<1-Rsw{i6b7Jo-Jl|I)9$bQ<&HsFECS z+|Cv@H8MpQHJDDlr3 zt<~=6y4>Mb>onT?EH_ueW$cSdz`lWCA+skjC!@^q-LdLPdYcO3di!d%t!l0=S?L!V zn&{81zJ4kggEen^=SkuZVs=+pqeY1yXK&++Gy*;*M!H^hC1_{WUaXLef(`p~oP^!g zWS-Y{nHjC~eOmgEpG+mqIWe5&9;;+5jH0JyZZ^wk_T4(A?A7{Wj=!SWdw%s)t)Qbj zrJ~|%bMfNn>t$@Fb&0wS85R#!R8*=X4lX^4YUbU8lab^hVrbt$cH1rKH}-o0a_CSp_rwcH`zXvHmcS zXP+bG`_d|;sv-{F`rg+US9oVb+`(J)&r0mRp3i!*QcOWB&oQHaN#nl3-1ZYHbZk;O z`~}mgPA=V_wklK(wHMn}DT;n5E|wqZs!%U*ok_QDKQ!KVslVYF2HAUM8S78S^0>?K zaVJPKD;XOgTDRojG&Hu|K0OH*__P*2=}Ye+li?(x~H)D+^{v`Ag#^ zqQWxGst#Ed%w!f%!#gn4Qz?TAii-a1O&8wMY2`cb?a*F6@%uN2u<$AAsV@~0`D5+d z;@QhXCHrQNrDtbnt30&wm1s^o^LFW1HveDa<5}@e;{yrU_L6TGvQ6||C!Rg!_SVv8 z+_*6s`8C$C_+G&HvSrJ@`tFgI)<*#R+%h|swbtLNr>93N&Dg70V#f}-(Z0H@?b{I3 z*hz9Ymx9?cu3xWZjIhUF7rJN}eKk^;WM_rsc!&<)LnF*!=f^;SgT6u*wLHS-8`5>^ z63q@AIKZ%OUAusOo}*pNm}cr(&lM|Hu=)>(I;Mv(;-F0Yo$7}@Rf|-{xi7vp5zGkmG4J0WE{#u4R<_C=I^@~x_M={4y#2Ld(Ou4q_u5uuyG)Jw zJ4jn)U-)))Y_Nr2VW8@=qG?l31^~`jU%ut*t4k(-zFjTZxyQIn+0-=p@1p=@lQ1r9 zl2ctjGc{gUpJK?Hwq5>S_iDG_*8=$U6ThUHl)?=zc9oxM%CXC{`54@boH!o%F=&tc zuHzxu15N;P(ZCB!mMn2#aCr7PeE%YEO>1d=M$UcvzRuK-^i)OJ{r-7o``%2emPCZ- zt~%$B@GoJ9;j`WoaDbz>;mAPlqJ+PkzSdss?NqjK(W1P}xxS==0c#W0Lx*l2y1Q{} zPf7a&1oB@Eqvo++Eng~P#u;TGKuGa6P2r8X$<6Rg^+$W`r%%e`ChS0*s*5Q@Ki$Q0q0+xHGJ9<|0-SkEex9EFwcg|;85S*E znCs~E`r5KSgtOtm7GSNy01=Ky#QL+EE>{QV{ zSUI3z9X@+!W>fqsfX0(QVqOPvlmXo&zc( z=%U!7V0O~N1u($3WbSv2ZO6OMPi_Y!CTkVAx}?Z`#hxc7C+}Y52{522Prv{jSFAfI zigF6u&biS#eT&}e7`=jKC5M3*UEgh992t#@uFRi%(G?n(JXldtp+vw|@pML=-bkRX zi_j<`GQ3%hDgze!x%Qt8)fy`{BoZevFffpCErM}$Sv&5=cgaN%8nd+U@e0kx$HzK^ zFa6MXEa9NSvhUKb-wpb+!y8;CIv(m37%MWeuq62S{8@SqDZAmt#VDgoqeCaH8fSJg z&RsmXV7w~Sp>vawiHWu`pbG%|9zX20J4trh4C+4iQ`bgJ$^s*hv}4Vxo@35=OIK|? zJ>j^2|CJ&yrYLw(l3vzxLYLaw+a)`tXL+*wzh-go+ozpjUNhYAZE;sc*mxkL`p*L; zB_)+iR=M8<+_03AtXtti(TC?v3XzdD4gYXBKbPk;-s`z5)Q5e?u3d4iGm}RY6i!^Y zklbOX?=tGI=g`5Jq?`5p=&@tJ#LkH9*>h5Q`scN$b4@d2uNJMgZ{$^1Qy-sAX>-jt z&jCiTXw0^@5q})ukffI7_w*Lu*{;t7LTMRoB7AA&=%S0aXQqj{31*m!M;qiw8 zNsPZLkMcX@&SHtdqB9 zMW|$6rkmXm`KScF4(#`1sH8Uit+&d6sqWlV{M?VED#3d2?8)H8i^Y`|4~#0-riN#}^zRbQiO#13akCwl*9cY-zEm z}k4%o#H>n4OxCyAXC-fq(e!DhL~N4Ek$9Eau;@Wpf8E(R7B zUWLh-K{tMBY3U^0!Iy*iY4IfdKK17#tKMzAT(VXkkpW~`?CA>QNM5L;+ayak^7Z+D-eO;4HDX$}9m}KYNxZ7M5 zNnkpgE)?#mkZ8Bw(0G5lJiEjA(8-=7J(GrolFd2~@&LLUa_r)a)&oR;jkU4R1$e{75cDA`_%w21CcJ_#(VqT|3n0?!FyC3zR1xrgy ztB_kHrJk}r1903oGjO?JB=GV;qh?mKV_aS0#i2I2(#H=-wg)S#8%yfVpBejVP}&LX z+Y1KBHzd{KJmQsk?#ltpn0D?UnYSW>K_u8&wV-yIv0~7e7BI)uNORFWmN<~Dp5UbM z@p1JdM{XB813OMuh0UryUzP0G8Ds)LXc6QvHIN0fIe;A>7zLNLdrK#3Kf3vpKS=iP zp?3d=4^4tD_f*Qc{eH`KB%^`^KsYD~sHd5zuT=PiG@$Xi&hp1`aEk84 zmjfzLYb2VrVI+WfuyuVBFW+B)vBIq*p%(h*8Pw7T`q6$BXQ{! z9~GU>ftVmJRv~4-p6Yhr1{R}&Qx3gxFZ6PnN*DTD`Bnpi_2rKjyB+hllDnuX zr#|Sql8&zC)s;ngIpd}L1wUq|xRY|9)Fx;<+0DiN_$<%HTT@}LF!!@!BX;BlzQ=vV zr!*6#aWgNA+W5}}b2C72x;>3nw^o zcpHhO%KHiIXo746dHBfT!@F6Qbr9x(B%p-g7q>+7%$bO(UyaaixVCRUh(EHJ`rC({ zU0nQwf?^PSdkOOi*?aMr{DHkXGsiOZ=O*hQr+L+l%|IM{0!83MU7b4N-UKIQpoI0lSFI5qW0D%JQA^NG!8+L;8eNd0bI#3Jpg6BHCQu&+wowmW?Jx}APgj%xP8!>Kkv%O!llGgL-n2M`-U7Gx5Ci&~rLGcT%?nrU|4<1Bf z$VA=&UaAIhA;K((o+*(3@c1}?-ROEA4M?9$&EO+iS(cBr(oMfT8-&b4^Y;wv!N00) zAts(QHh$ju@lh0DQkAuNdeh6xeK7Yr7hO<|0Sv`PKM9P3Y++5BNrlbe5`^oLJH#}P z82sw~{Cs=0J(l7DmI{M{#7SgZ zuD2$Rk(pWNN(`P+t|6O5n|_ZZ5-E3QeGfEbHOR|&CJIUvH!rUulc=RC0_azrMcWEB$?$hp&5{!4BD0~FHIn-rLb6lK*IF@!a&+`yM!*4EZWPzJ|+O$fmOqX>|r;LS`&VD|35 zBr4JTwV=*|!8Z1}yVJl6%TI4hLtuZ7>1Yv>De4DMPusDd;2kdBho#Tb(}hZT1O-)~ zVhH+0+XM=k`5NUpj+(=rOO-d{S)J7+gh!{V#cMU1_L0Gx_5l%2&6du#c zKuhSJ#W?R&3}y!e9iMD`aWQz0$-Ngcc<*lolHtQufc*TcdTf)fUAsm=&NWZ2hlo{l ztP=HtkLJ<-{JWJ1=c4%^cXiFLtg7NoL+NtKvSmz1RQK-Kxl^n5%a<=&DF!zpgvhHo zsaIEOrkmaeCO8*VSX8w6$Vms1DS-hW7>T${+8#8+lRr<+PwwQepEsKGoQULivr^Ua z!A`~0c%1Qrl3cf*S}0W_G$R*k8e3ai<1tqx>_OCYdi7rF@OdwU=uR^xQO^Cy zv+nJFc<_|0?DYsCe|=adK&C~|v#6-PvYtpe(>FMAAtO86-gS+`0JanHjnr zv76VfT?1a`k0%*m-ci73n#Roe$~F*7 zM#VTqI5|K3+cURA8^1hPWE$AA|M z3N~WQH`kt0jFk6QgXJ~$q2dT4Rdt$-k)ogBYY!hidJ6of8DZQOIae~qxVEko^VP^BHssDl)bX3FLCq~yYGsgo+YZ=GH#N^lyJ)t6v z@CIu32AyR=0d{1R>1Ku;ilcskfgHEqe$!)tMoYv{2nMNTV$QFp zpvXtTGqjDZ@+Y2C-ZlTm=nD|60_;H88CY2n5k>=0)Y5btD%?Pr;QWK@C@WM(S@4(r zDnUNJeoOy*6y zv2p_!@&>VQ_uyLuqpNQGk0@unQQ9@vye_d{udAyIm|ByH%+)+pJa`kYk#YdycLtf5 z>(;GXCz}RcO@auuf5@*dLbR7~V=BrpKJWgv5)54xm=Xa@^EPV{^ib(;)LwTJTmS2^ zZT}wV9K`KCtrO+?Du^TAja`WFJf6ASid&GthZkExEZv$Jc|LJU+>Qwx}1 zt7T-Zl6C(hy6qt)Mv$(oGT#Re=$;{RMDL{xpdV=T>DybYwT%IUZ&p_8xVpLq?>=+Y zC;(s=lI+GK$gs+LNJOT6Wt4P|xIEb0`zhjDgplx86onZ!ZtT|6&#_hbD}AZDkwto? z20ek4KY7x!v&9aYp~fI;TAzF-Koi6m0{toy=c8w-5hOfU3bWJ{J>Q_ZX3d(Ll`_7p zuD{QeiepV6W(!m6G)WXcTIOD-v3S8fdwA38>ori%WjeB0AqRZjuIuq-En~SmXcVH^ zQ^_d#BRs$k1a`au>YRXpz|wW!Vy|CcTslb@3i<<9Q7h0)egFA?4{xo-L_K_}u&$J6 z@7^yYa=G__vkJ;XjhJ{4e!O+LRk3xyh5pYse=X~RcISy7ggaat9HD} z02Dt6$uy;mtT~B7GNV+FQSSc|)|A%{4Gjg1qQEc;`IEvA$}^M=BylleN4xQx#Z11`k}nM7P|32Y(QBBa$+SV_3ypd+5J}rQ{|@& z#sYSE3UZm=t(!Nw1O+QkZ}U?Hx0s%uZtMf2FmKLvpqx;Zje4A$PbWK^Br)U9pFgiy zwMxkEk7u7D`Jyf3z2GB}^TE%QfwyG7%n#&!Sy?rNuSSboZzBQ&H(v8p)}nG4T0WT}YROWAja&G2^xUY+buf_LuR zd61Np1Y_`q!EtkOl?WbHQmR8u^&`n#(M!n&%e;6R6~)cZUy(=u#~+`dHm=%vz=436 z71cz9n4O-OU$FC3)GC99Us+kng9_fw81!}AT>F}d6f6lx5BLJH1`5)=S2j>D4@&q~ zl#6gYeC$|yJUl-EI{f@&3qIgZD{OW^dt%~rFDk$Fu{|d?fcn*yZpHq!W zdD4FWw#S3#AtJQ5blqZejRr~xT274S#{3&eQS#q_TbDg~#|_Ul==8MM zofPmfhe~-wNhz!B$&)7x%*^LF*8KPr@eyfX+t|#^?4SAT6qQ6cG6-k<`Ry%*lOlwY ztG<7D&~ZVmu@Cjio~Fw!!t>ifMek>7e@An#j-%js0&d2e1`(Y~&dS2nh*iEov4ydm z4Wdx}wc9>a3WIb%IXzM_A8Q?{HH|qICe@T`*^nLsGQaBCez}ce7s4SK?j){Gfh6}> zDkb^VL&1fpVn!fmNlQzM@;24QY;0_(|7#l$7R=?-vr3q9Kn$0up@hjJ=LQ;Ih+piy z>(t-X6*X_+C(wj7nie)wmY455k!t)g*l0KP0V~AS(k-X#Sc>*Cep-vY>lDuyQ z@^(&VpX0CY2%-t+PYt9Aub%CC_E4|#q>^NZUR~^|qf_I9>VO$^&$(V=WTsH60DF9G zpZ!Jz`uRj>faI>abZAOPCw3~V+jTs>-x2C>u%OXx((A(40%J%Aq3Y=D1T!)u8qCer zY2MUaqe=V1FrxV@`bGlp z6Jr2K;oSaCO=w=CdL%3$>YKm!*-8qsI~0)PwUSR?xw&eS%8x$j$!@|dRRLZCY@cmJ zzz*R3a+(yQi0+w3j~+Nk`rii!t@u=zqsH9#QM9F+bakLQ>)`xY-y8e%(0UoN*>AJI z(CqpR8%(~A5_$GA=8X6~`(aqo7jf_GixDn}G*Cg4dD&)7uvP)1D2Aj1>K`;aV)-T2 zh>-J8=iv_qrJ`{2eUur55w#Dfe_UKhNEKy_OdSg>xFfpt8v8Id^RhsJI+qrx=`~qa z`s0(}6CD?BuK0vTLc77{Cc(I}TLM3tUaBuzx=I;b>dl)s3`|UMSldVUutny7P?01a z_|+6{6rc%Ft|P4=mlH-g+^ugWRn_mWu4g?bDJ|X7KEPAIofvB~c9EBU2BEZmdFh2LqS1ZWo7a~HbgJ%(tO`5GT%&Lm|>a@_{)4@;$;%yEQ z|5-yMHg>X0dag&0Upw;{#`;t1kbMq(*Am5dbO3ykjPqD$lh*;Qdd2ePLxCfG0*vmx0R4ts-S-Jrh)c7bPPjPt<({J)&P0_Me4Un=nSf$?&Fi_gOO-h zj_AFZf-^pU%XXPMeJCYlGXMI7;(P}9NA*-XN)Zqf)5;)vUbE?Xn?V{BK$bJgjLQPI zMpcso{+508#!bU1=gq{X9*G$z>JenCv4`RD?5fwk+_@%BN5 z?L#?4gaV7hRPLuIAOz_j&6|QU65X;!T6#6W~yQwkC(NOF!yQ zbj~Q-EMLAn0CS5&rHzjg1?F|y)=Y!K75z;w>jcyKelAgH$hM9whTd;%)XdMrQ)ZY6 zClVaI<;#Tlg&NekAjTP<{e+s_Ch;_zk@py|M>NVO^_TM627I^@Ww~S8noC(OFh=6r zZ{NF@Sw>`82sc2(*ain`D-~3ZAHPRLsUT#GuZ|y)-5knFMzSqF?@MM!hs4XWsR-Nu zQcm%w_R)v^+4JWmJ+?Wd7mhT-B-HUFy02WZf@{RJFmD{t&8T_xvvup&KZki}Q@sf& z5l|_^e-SYR<$ot2UmctNYO%oDTMs^SkJBIk%KHGdYD#3)B(F1qbC9m^7nbEDkEOrm=#8!p%xV2UU6s47UGMb;;BpN3DuAZJ6N# z#t9ODaT-1F@j0zYnkgF6OuQ+YL`nV1Z~L3`w1E{HI2=UUe^qz0sAtD z_S)E35dxnf@*yb!wBd5l6IWrX5}-z3VCQ4=IWbY!W%&tMWVZ57}iNX+)-8pxC8 zyQ(aJh8<#jr96_7kBhG?pvicVUPBqWOK1x+GB(yCqzfv1l26|T^;ZDqF=bPXY2H%EU{fF}Co0Qac<=p+WA zd=2}lReNpOYBdOL+&?Boo9!cue;|?=H4lOov+fyi-?NJ-6tl>ykuc%SM143-Pxex{ z8j&*NV%PD~_$T!G*|7*ytZ8@^9DvmO%V3}ySSKk;?okx|OYXTyJSaK>je0!rTkSZd zFe%312zVK5THBFyvO?%Yx*RlqaDtK7j^rTH?Mv-yAb}_{bbfzB3BGT?MSo%jTu+1W zW*Ec*+*CH@GB-0GUQTp8Rm; ze=#baG1HtKkZGTd4UH z6%`J2%GUa9J;;-W%6*e{G0UN0W+*7=;p0M=dd2Y&u?Qa@AC*BO`i?iC5ef>S8##bs zB`3ERy}W%@O44>oq(LR|B}?A3?Bc|UQK;VbntY_Pq5PI%W;y{eZ4-A3d(TZKOJ%eY z@}z;CAd(xE258oT4L)&>lci!OXv{mx zx^g{Fa{Qh3QoBhn@%gWr8D+k{zVnn*gE(UK7QlQi9v<7Ig9i^XqD;U0Gb2hdY0O2* z2!h`06qCRZ*zRNP!DP{?N^}w~m>Wbo%N&r;PK8h< z>+<+GI6fg>d3EeXK`g~$5kf0fG2OfkttV(DyO6{}e+z}@RXbCA8#3Z{9uMi(t9T?@ zVWa+4NfWI@&>NciK(P_pOYeDbM4{>4i+OLQ;3L2!KD}I1cBM;~E~Si+AaP+W0$&s1 z1j+{)@~Swc^klC57i@qgM6F`&Uc-4xg$nxw2?kFIaYx zPdvvXLgqg}=wz*d$ZW!1>bv9U?Z;MMQlDML87KE%s#kyWY2XD)S>t;9ZKWJ)_NJh| z0|z&ewsI7%&3@FU5b$`9O*#=_*8(n2dJhMi^Uz(eOM$36>-qI~^!4>0v@A@FgaPzc zMR^;Ip~3f*=}ok|b$`3XR(p5Tp4&5%Xh|4FJ5x9Q%^18A5m%qSu4b+j#-^%`tWtw& zZ(|=Mq;BxugleOj+l<^oMkNgWU(&jQli=)+^_+*~NOV*d^sB>UexW~J%Xsd0v9v8z zn}$mtfBmwR9D27-++{L7Kwj zLg*+ucRx~fov)O4H_ePDxzzwh4CpOeyqE))O4{ZER|q%Z*hlQHFy~5&Xrrb=)S+vn z9C_}3sR`L`uNOLe&z?QgG={ZDI$yKKs;eU|HT6wTJEN<W`c-u$W;`;r;&_WRp1m!GefQ65`Q z_@cWx*S{%<3nc8iKkXlHyy*R}62%XyL@w+f9LyC})uV^jT#I)eYoHK>Qc(cXAUCR6 zlu++P4U`U0pIcJ0N$?JA2kl!CvNA*Hb=)s()!Zm}6v_nwTd!D&->V*kep~tN?JY`~ zJ80$})(IMlGPZ^>k(X`0dr+yUnY7l)2&?{`R@3T4&b(O+ojRuuJyR-ZyL>H+g>9zN zq;Q(kxFuZZ0}(_}9mvjSvdrF3B1#$33VMxB6TIktnR2<043cuGpyr@{5LY>Zpe@v= zmP2*`jHNK$Pd*adV(%labM4tvMF56>K|ulL^`X&qsy_!h9&Z{N6)EtROVzH;&q8+k zcV6x8i_W$5_&O9ipzLlWX|h$4T7>P;%L7Iit(FLfje^Abl_#HhTm5$-kv2%6X?U;( zTJSCnG@1oj|6UmD>+Vhi%hxg<%pJLh$bV*jPShSKK7IOB1IaV17FKJ*L8mN2=%cgo z8RR7ZenY-LG5rnm+x5M((;W4HfG-3!To8knQ}P_kv03n}hf#o^ANybEdV*Rlx~I>c zae~m~(XUuhiL{BDKuKcvnNX3{$PFCEbqW*)tQf)P)U z4D8z8Egx_Ac7bE(&Z5)XUQJQngQCVEq_uheac=%uoOChMymjkV94dHl)v^E75k;uk z?ME;_NoW^T<>*98M?{V`L$szG+>ezSr!o}^Ft8i9Zo#(dNdvd}r|>HTmHGt-n^W3O z4`m63A*foBCL1HL@Lh=V2R&&{HHo^~Q~?YghBRTd6P6>xNtr_7-(^Gy5HN)w4| zUW{Q;SQ*BOZx`&R%Mc82kzOncrR^YEwhZI_|A=vn{9If|aBRme>GAQXzbata zQdB%}M~tRqaxBjZdV17vc5fFG(?AZ+EHkbMO@J&w)j%$|Pz$i&-$NZOZKqNw4>{qp z*$JIxdB8N3>Z-#;ZJP{=fQ~pPLC+$NP!UM-4-UuG&C6lRLDVXJ_&W^&n&P@eRVqs7 ziklzbnhmm{XJ~z^D`*F==m^<+BvPRS% z5xS}pli;^S#Vc=zP-cLN(BYHUW!D-UGj?_RCEz{iEFTbbv2#jtPg0%TN4t*3i{)Lj zcew?FE)PsKx=kFFz>&lyy-R7QYZhOiDSuDQ9WDv!qZ6s$a_AnjX1Haz*eWIwp8VO- zq^`S~OP0|XxEC$x@19GI*2QwDa9k0;+J-Zrn{krNxxAj`a^o5_aampw zUr76HzEF(DVF2!7=sZ1CoKc5Uo&smyTwi!;aiQV#@1Ybl64mOt%}#U)7?t?pPie~1 z)OT1U<%x7nhF_z{vZ2fM{UPE%OuAOutD$CPoqw8KRkU4Tstj#0) z=bM%7zywyGMsV!xaPIH6J9`c3_1$%LJ+@Wx^Yg3LD;RHfvYzVC5{*{FI2xTtKBhn@ zVXtAO$;it3RpW;tXF1LEUS^|B>F=*Cv+EIt?_Hx8=eUQ8?nVjwpPQxK>d)LN1Wqzf zLfB*?h2o2EmTobC@7+UWs@5AsW7JUfNu`9L5m?b(B(JSxRqcU%wrw-Od92SU5I@yk zLeqMFLye3)-~RGflQ5U{Xu#KAwMmejtZAU2(GfKBJNs9lj<@Ub ze>PsMC?8zpmdkh1j`>bew26TnuxWN-bNO{*a{|7|k9?7`t}YAo)~S*Te!W~V zzL!5z>#@d$I7sM$lN1Rei#1-@7)_(=rsTz($M$<3IEltz6S_4Hx+Nptty5l)m2D&3 zsecrQn3BYBz&sN360mH{wnrbnn&wH`G8+4beXX=DOTee@;pl5p%^s$6$@}raog!b7 ze`wyN(dK&r&OXT9eFoxQ3OWRLe%U6(%?2cMF8%YN6ilZf1*xBZti^5aH%{TMAqN?r z#KxL?^`WG@hhD7JT}TUC6nX>Jd-yeQE(>XY`IH8gZK%Vl!eZ)xgJ}#%BojoKq&z-u zZtb{F{iT*@927%)?YiDoG}CX)Z)h|#jnuOW*TNE}tPGjXr=M^}4V6m>8 zh;Q20d827Esc=4@tCRGnO{1|)yg0(R3FmD*LHBp4Z3w;tuaY?A&B}s~_apJovCfBm z$zp#BWV|q{nPMQ6}vYWB_#r-J`IJnm?FFkqU*Fe)g zJ9Xlc61+mLzgWA#a*kvU~%D-oE&k)QWn&iy>TF* z5Qjtq9c6YR{`<1KFLGxPlB12^;D6(ZvQ4q^qx0)=Cd-;fD?R!{=dE-SDo8x2H;+p& zfP!re_v&O(@m-J5;KPo8JPqeul+8bd>cN_*$CtFuWq-SAjpHngPnVg-Lm*GS^k@{O z-VP1dY?w6{YU%uvDM!-=R)V(OT|_Sy9xf?!&<fIMsC=mKz4k8WmI^g z*Zylu3n30hrdMYz5i_5l zu~Sj%vZA8bI5>vq8U%;4iII33@ljLXiE!mf zL^VW7t8@^#51kAcg~I$OxZGcYpS6R_S^B;R{{)uxC;65KEP~s}p5hKAQQ_GzmoZNiW#rAwCf&Rk|9a&coN{ZAj)_sQySLq2LU4AfU~XT{ z-f#_;OZ8{0JN(t3OL-sMNOOPsM=Nd188a(s$yWD8ZIgXT-Vh*EyRI0Fp#?+Kb@)Np zQ}J7j7icmn#EX)J7G;wNW#u;Ym4lo6=z040w~4187yEX-x_4#kKi{|H!lQGk3J<~- zE-xHNE#VF8e7VIB&S>Jsafvxx5tiXbn}tl3 z8y))+00QF<)uhm2&91`w*482-A?6?57O~(@0fToQhi-i#^I1+U(ZNO8zzl+9HNo8# zv$vbRAfrI)yL2sV12Kv}$>27xeFf&bojgX2eg(_^(n}auAsEi)U-87ysjte+9CYu) zvNgg6Kcnx&PkbRj88Z-^USAiKj*tVQG?}B@DWm+jA{$yrHqrobFV0Jg{Q?4tND70L zsTnyT%tPZ}udbl6?_M*D&dv$@6~FWY8h*G8Vrh@ zDo-3k-h+B$({+{waj8f*g*a8b8E9zKRgb(j;;FHsp6a4c2jX#j?uO-+yK(XH@t2v* zVfjyBPipzXl}Wg-V55|?eZ*G|bL6DkyF%@sd^&%&96FEzI^`VNA&Y!Q$XjSDd(rx{ z+=fDdV&;?GA~cTp8>4e4*<@CZqJM2e&XV9598W8HB6nv+)1gjCBu_r^GUVY{-TN@3 z<*|v0V=WI3X;wW*Szy{cy+;B90qyBwj1WJZsY@77Goqb^736}?mg($!^fI*JMgr&n z4~~m-qTk|F>%G+T(8Puya53h19h;gRFJJ?#;jm>2QaN>sQF`KoQXBH*J&(C*w>+%w zhHUQCHe6%lDuH`VZdfjI-v;B+xbgT>11CX)2eS6xY_zM>U9-lTSR-yY(XBTQzJh~b z>vL|DeMJT~M9J%h<@SrH?`}MJbCo9;wV+6oZ57UFO0H;HyXiA($p^A%GHWn+>;}A2 z3@3uyX)7<-vL9kDx9v)qtKc2|y5TgLNKGVYvQlf|SYUm(VF&o}*#_&v&p#LP zfB*G=b6GyEI;E~&?9lai1Hmg1+7X_LkHv-26vl=le*CuFkjLh*s6u<7n|r_wMO`OK z^^1@K)VnX48j#>f(s*Wz>r~*r%a##eu{#H7%Ra>uFpvTiQMioF`A;RuQPpz@J2xyn zcV_lyek~%0naM2(tC+=h6I6X53w1x5;AX-SVT%Y z-I*N8NPUGU0kG`*k$f=3b+X60=9D^P&JG&QGzG@ANfab5yXX0%C+Lb4K)Yl&z-EN@ zlf&saOg>OBH(PJt?$wTK9qvMpn*Z2+^07;=muz?kP_=!V0dNYipZ6OP+0U9d5^RVn z&xw;K*Fo*Ni?ODD;zjA~4xI3PG>Fx^O(r2|6~yHn=a}tVuPhnxFvtL2Dmo$0!g%V` zDQf`hVw}%Y?G8YTr5q5;*-vOaGC%|%?}VP{d9i$N)F<8(-^u+N^5Cq~BVluQp;t2G z;D!~`6J&6|uCYyT!L3CJ9v)&?M#F1#A{^%+>k|OA^%nEmHEVDqkBQF3kHSj^(DA87 zPZp6RZh}=C`qn8)q_{URJUpNIWoOql9sSunn-b2bci5E^uPiaF4kWm`r=qOWPZbZKP9nL{9qXKcd z-wy26Fzus=c6%4Bt(q7Y7;^krBovb&WF1-AcaZskVGR7oy*CPM8%oOBYmZAb>beWY zH?YMyhP8ay6_#6Kf>TO0!o6m=uHkNF<=oVmG)^4`O1rs67O0&bC1##6x#x@>8xWvo zL;*YPG#w(EAldr8b?A0@zg$JF%WbyH%>YdxRN_SCN@GxxVpK7RUYp_W2LSeobMw%C(uUMM=QRM48&_J~pDk;EV0uIC9vvFR^ zrg>1k4(Oo`uLkE7+h&q$)sjE-sAYQR(bFrDypig?;y#x zYqw0QF%tj`OxDqK5xPimR{m&0O)bhbO7NRqAQkIK4a5*PEfD-grf5KrQd~YRHepN3 z9X`^J?yEHQO|uI={5B|TK-HstL&0ykU%fRJ85IQAkegvT?-G>7_u{*+s^el><(VbS zGD~^D*+XG=At^;6t~v1SBIvhaqWPy^U$yU!xYg^@NtWEh;~y~ehLuGG4vHk^jWuZC zlAsZ(@s2I$6bW(!Aj$La_>F_NFKfSP%YK&}K@e&vS*jSGnktw-mXTD53u^j=SF`{~ z=ohlh{=AhtWRdt{Cwid$4&9;293js56NyvK&d#p9Uj6)b-IJ&Q+!=K4+UL*?!?1)> z^Zl+QeAF6INlx~iALmH}c&ll3BQLq7%J9wgkKqB`2POBS7_EVaae04&S>|q2DQ@2 zg?wV6(=J*tp(rc+16PlI&a!G*I(kCiU8{wQX^W=6zrVogSMI_&<3NhuFzc?n2>@V2 zcl4*XdDYU~{fOVRq6@2xNgKhENjD2nlZ2hzp{nEi62_JloIJjF2Z>!ob7q^~9D~kH z0kp7%q+ndxU~YBY6QuTd>CR8IN;S1gfeewym)0$+J%$!X!&@wuH2Pi8q!m4W;SoXl zq$BW<1x==e+6~;p^W6(gOgry405*Gpe|FwQZ-&zliJ1hg6VyzAHRQTKamCT$v*iIl zZb?s{X|9Lawxb1Jr$3EAY1LDwn!#ScR2brCh9(M_N{I00|06XMP znb1l_v97rF^|gydBwl2923x32{Q&bo^afZpSKX-9GRU%kncBBepbaSfn zZ>^)f-$}mY>5GMY+X&JfT`F@lfX6c-vw^EzdT#n%r`AbnRGuTBK0TWt)vNWj%MIte zak%wTgIQFE7ZJ)%XlhRQSCoZGONWB_dYCqjRe5-zlGEk2yfyqMStB$vTx|Z`@lc-? zgpyxIexAT>Qf?W02Zkcsg@TAI@qUMPrynWuc~|J@M9;qW>24`-E3Ze_m4$kCO&0*I zS8#A}H@ZceSL9?EEn#K|!=-rH%@1OTidCC&&C zZO2^#S4gYfyDsydUZ)L>Sjd9mS^neFlD*N9Ptwz^Tk>%Qgukeou5MFwuuMBi{X=74 zt-9{wmLyK%>5iG<3KXyej14YJH zluK@KDZpo~%lCG%OSQy?pt_5!o~FiTm(V{#!odR<7cdxWWZUmv`ZgbSI2h`mQ*1JN zsB19tQPk>JBez=od#1R-@r^$DJ6p1mFFJ!w zF~D*cbPC*A$)CGB#lceyMfs8AL3tek+HL3&SC^e`>CGbYw^fGDL6;L#rM**D2t;qBWjuGLo9+|w}}`LOjNw_^J9qSrfuOR8(44ovVS-;0+lZ5`wbg(F6@_>`Bn89=LNFc zZgbm6U52Je@^R=Mz?iT?)Dnq8d4IxF439;o3yo_J^Se!y;wXSIk4Ewq99CpSpi?}T zpR+&*@yY-?W7^cs_nQ>r(|km6OBWUjD&-e)01F-lOGU0 zO>LVnhT72Sy#OTLXjf>?B|~ps|AB-PYqX4uI=app-r>#kfbn2S#$Y z9-WgmiID0i4%JNIpf;7Lus5h>TwuOfCNSEZg$p=}l@QBvhr*`6?*bFH5{g|mTM=Xu z8kDtS03rU4$Jwl~L({wLXHq9K#TNBs|41!uL(3SPK)f%09Zs&4PVG5;iWN630Kv#t z_Aj7u5&%x{%*Ere(`awqgaVrRg*>*IZuy}S?j%{jZz62P<&LLU9lwKX*+fi!5KAFh zB~K>g<`+VO3ugNYhKq2=;8Z>2l(mmcP(0Zix2p~!)kaZE9kL8#7;W{`>djpt7muII z{97#^oJ{AbQvo`RdJ#!CK`2r~5}qp#?p&p5+U^$ANi)+l!Di z6EZ|Z$JMSsuVutuMAxA_yclAUpe&-;)?FbN4%ng)F*XTcq}#U{A;^{)t3{Z}nmNto zSv#Q_Xbi4)lAfEWX!kwJr`adpdR9wc@i!(X$O{6vb{&TTE^-~4FauU(w`?~ zW^lhojy(+KViE8q(FiJ5HusI-_-`>1E;GSQMAzE}ib>n#+sO2I!C~E7^ehHAUug|5 zke7Xjav2-9dZJGMYAa!3VF8o!5CZkuh?tMwu{zfQf|`M_B_VKU5th)LhIK%kPa^uTC`68u?U>HL7xrm4Z^fGyB6E~ zakyg-Xi%N-miq5<5wmr=e;% zF{d}SMyd+sJaBN$4tWpoZG;i6I4g6I+ogh4yC-P@;t7)|OU>g0FNKy~TYP30O3*mbf9a}|M zv6W40y?zz$`$DQ^^-#Lj#gUv|jIJrx1g(tQZB!@~m6`?8SPjt)N z1(YhcIbHa$cVCO{Q?V*X_BMsZtHgA5Q_VZ!^fp^*y^ z*aQQ;3qvK>db%;>?AY9zJ5qj!msOGcpVT z`=71Z(12DnsocpTq9Kum(PMuPu$~ZYvW4_}zx#CK&={$Xr#MdxbMW$dah`lm!fa$G z?hZJ#icLy_RP}Jbk0+W1cl`2)>_vA z(CKA%>(!NOgV6MN#M0{P*w2&^{ zeyDAuu(@h^z3$~EMl>aGDa$`SLo`XS76|xHM68-62E(szt3+NTFeBnCEj)SsidLHG z`p$|lHWUKNH)*35OX`*canocQTGlerX!E@QvhNN+CpTR$1+15wVpppfMSF~ae22k( z;;E)<#i^0V__8xCFr05d&!+2pmtIgSz*`EDI%U$(%6vPd59j?DqT!_OI!H>vH*&aJ z5wB@7DZuuhc;E^&cY_`7i^4VW-{kxc`5?+lG}>)I0e9oqoYCZA>KnyS0-$lIk=HE2 zxc<*SND4^voi`s3G#%U+f}#?QVI{Wr<5iSB|9a*B<@ZNe(z^bHhlFe3QA{xOsyS&_ zQs%)VgjQyT)Pkx6j>>u)Gq5WuH= z9PqXOIV3Wtt++<*|Jf`O{#x_-uOSOzW~W{tH*ZONWTFZAv~tqjHos`;xYqjn|Iyx= zK=quzegDUdF=NIO2`QP7eTh)EGNl+>grtNrNen`kw9Q7*!q{R^ghEP_vR6hbG|JFo zEoGZRlB7~Suj`vx?*D(>=RVIl&$*xboZFdmX2$RL`!1j5`druhdSCAg;6a`oKe*%d zg(60?emAc+?nrw{L0j0^*nD%E8A{`=J6>nS$A`!wFlS5-*8lL25AM~maMat&>`kjs zhc+Nr<%s?dSFIng3IFnI<#}UdSmsao>j{=ML0iZ2sZ7;Qj5v!}`GzuZx!gOA{KTJM zFl{ThQ=UaQH7fO?@*qx}CVyN)ne7!a2*3t>;mpsZe^mk3ZmjDEQkX105pHK=2bjI3 zB+e`V3nXxhxuo|Kgy>EV+h?vA6UPrb+R78nu!{15neFrz|0nQqi1&z+Wl~OOW+tKQ z262V~B6j7HdA2HMOw*dNh0~57G;9>dB*`(0-+iQM9=>TiIo@EKrbt#t4qs>(2D-We z4@qQJux~@3FVEtqbX@Z#?wU)JyC13yrig=18Z|CQ(m+q)e)(lZM@0n+W#~DzsJ_1J zl@09%I3)wg*_G4?=b&(-X)`|*&xYyh1`dCnEA%mk8b)eIY$hwBfA43#BSgV|!G#mP zzTm~rd&+;n-A=`Uv0gKrgY_h!M9XJ*IcXZqZdxS!n?N$7-5M(96h^}hZ;oCEIvlL; zn=qA9WJB@o2fDAopVG&h@%4>}i0~DK#QUuA%>L|mlNDJrYcw{&9gqOXqcZPM_M_d4 z+Ssp}^DLU(UbuhrgfAoe{xRs&JR8_ewzWj~?fxn}Fqi0+;A#TVaC&7z*avI5b&nec{ zIrh=~TwvR{sOxeFL7TmryL;umn@?(4p9^J6+F;D~$A?_qF`(;XcK}sq%iWMw&dzIu zxyyW6|F{iL611-(MqHMX{piIHr;A1m1rwWoa><RpPp^a@VUPYAA{OdP$3}N>lC}-bW|@7IQ_QJ&FBh~bH{YGnd9B>;bk8j4 z9`^3PA2=IR^~LdlQ}bfQK{B}_HX-)6=?y9rU{|o_rcpVZqGw}x-*e~7d8MbyD}lic zJh;d+!wdYRX%w4eZjf^GPCm8(wSeNyRz{TA$aX#6OLkz-04vL4+XgwrMIYrTHlhA+ zP1_b_`#amItn*^=4HhgJ{^ww8+FA}>`Fz*lc>M8?a=^hZw-;*1--hG2kMoJr&hZM< zE*?EpwdWaF-QPam*~3RrNKL!wgn2lrxBmA22F>Oilfz;((M|n`0U2;B+>MWNs&Qq? zQiT8EvuzZ1%jtk?lOjlTFH`OT-+YuK=-ItoT-n=yzv8r{XP_3V9m{`kUT`>JUIlpy zKy;PrXA9*LYDwh(oUT#gyDJ9p;>`K-dxQbIiivQ|B{^i*oK4n2EZA0al{JOuCz_T6 zBraTXj;-uVjQH;H*vd}fdL(R>W7iaed z;!WHYvtz)#D7W2^*7`nnrw@RHbt%WO{c|@e!?&Q3omnyv$kHej#GyPu4T`zwj#%TX(;ME^zHej$c1;5;~t@be;3_`p+z%onGG_FGo_T(Us zo}g}MX7-P{_s4b|Q{HIFnBCu2DJ+hJvfU*&>?LO^_9|<{V3O8KU>1!MdU9JRP5aKt zJABT@*!-J)gNh#jI1HK%c@m0k1M0z6q)14zwSvOMFnx-H-xM@$E)dJ5&0V|R!-{Xz zmX&^}`?RD{W|Ge%O0!?n?ZV54SA-j)Pth=TzpDdvTM`t?e-|(ten4zP1w-=n6#}M^ zOeC+DTrD$u0gqwsZxRZU*M(@>x355cQyvQd;s}aU%J@dTOz0h-tJ{ZgtF6(}xrY_Q zf9zOfrnbt&^v28v+f!a&KTV?&P00-kCQ9w$%4A5k6{{$V3Ihbqp5l4@|3|oV+&PGm``UhI-M2& zAX5CmG2#cF(vYtz&ZVB>2hROLE{!LwQrRfO%~DjEOjCZV_+|Bfs~q{G5z0ZWAs41ReiUdy7-?y8$?71bMtf&by7Cl* zEju>3id7QfxR*f1;1nmbU9PRiQgL+bmlMH_HKA*weW=nJa-Z+K@C>g;pw`;%DkZ)%f;xKiD$gUTw}9 z`59x|#0jsn(NAkgP6a^(IXb(HN$S0hq5k%!cU?^wY0XAEsySDBr=4YETwxMJXUh1A7_uJ|PW$NLw}*D~ z*D~r~ZlsmKP1L`|;aC4*-k#NZVpDDup?uv%&Rdy(mt}n8#sy-!^%sQA9u_d@%cHgA z;(B}VG)-jJPm=74fXi`Ju-?WV9i&nv9cFEJ(}dnP`oMD}lz)1#kvZ_GQvQ~@XIX$hrgDQZ?(K`_tkc#IE#%{RT>e%! z%KQ#>U*1af;s-E|QLrbalEd%DnxaGD4rFu2@7LhcAM}zz*!LSpzo3LI55>X7{8R?v zTUiauf4sG}=mh~oXxrRxo0wdyM5bArj#R!Nc^~D7`wY9ND{j-a+4JOC1Tlmt_6a;X9dbk%_T^s22{bt%wtJ7l#Oypd zfPu@BZx!T_WXdJSkodBUa?z77*vs8!@Lv7rOucRSwK4ZyZ)3B!y=wGrc^Dyn?7bbj z2{5!JZ#b#q*H2{1$mpfugnfFW-GU?YGWINZWp504+lNX6=hp&czqwbDVEtr}PaWx~ zHT4)5FK*BpYr=&181VS~={V|MgT}`V1to{H0Fb8nL@23}qSn=o$1+H&`J15*Zpbya zAoQ96=*42f9QU4pD|ybl$At+)pB+C*p;H)z0HuP1e>t}IqdqI{UHBOK^W$(0RsV+@ zt`A5JXx~*fQ2+B2``}fPDAl0k+aH?g>CB@%NTiyaDU-#&vU3%t(2>9W^#BYf#8sIO zImZ5{vPfUl-8@tMB&ulW#Qc!X->=hcZD#JD)&Gb?+`aJ3wo2739DNYKLd3@BZh@GZpW6+DaU&i09!7TJ{ce0B7^f_Efu{rpZrChz6WUfD zS|nIDZQouIGpqNECN=c_aic~@@t_7ek&uKn+CZiJ6;%Uw1B$Nmi_KpV2-2B`wk)s@;R z$sm$r7~r>T=!&OG27)+ksL1=c*QOlgRZ1~Nk`XT3`L2T%i=M2z6+A$(Yf^95v7Be$mqOoEQ#_#*$jD{PNcp;8%FT?=yARd#f-XU{0k z?4X%P;3f%|TznTP=89i*R}*P5$ygdv{(s#U!#g*v)e@Cae)@n6f3izi!He&n9ta5H zn!7+MveeYXS0cUJGcOR)9*^*@XxWo9r=ta9 zyi|^RM+(FSKB5bR9|%$MLKHHDwn=Uhc&e>XjL*$YZ;cGXhPtX*bqfM2L1NZSDHc*7 zQD3KmzPBfXcHh}gcJFhD0~_G3_10el%dwE$=AjYyxU=M{Naz+ynGJPgSu4|b^`rdH zIlEWogl6P$?ascwwZP(R3T^3hb@xG}WD4fpm_LG3;l5>3g9jUd>E&srJ9=?4UzFNC zH8mlOIxw`QNQVp&dU91@@PHBUFN7)9Dwde)4ICM7vm7$;-ck2Dc+itAYxSSk43=ut zMI;K77qXN}^J;Hl?>Ydjb6>hghQntvimo#k!M***8Cc(ZpjPj4OI%adRUm* zso$5BG{R-A@O)C~P2dUQXyKJG>mt7?ers!N(rhUCcSow){cP}*rJ|@5hQwD}dQ=Ea zRgSjgg#_58tm7Mo74$s_fOM~~yO2ZL=O7}88!yP>Z$9jWNkAof9h#^VMxD@lw>ZP9 zszSrgc~SpZ{<=maB!zgI73^KIChv%Tb#e9$C@f{AJ2E`<$`@jTU&~88l{_dO;YAP| z>%us^gu(Q{2^o3#&T{Bf=6DhQ@wsFdJ8h>-lR@U#pGJ{-3oX7EPc!odW_@Y8AgqGWN;D++Px69Um6xpx=$|w`U5LMeK}bRIy!2h= z6YE}0+!PY>w!A8_Hm7dAY#9O+B`lO36}Fs#*N}mKV4YYswLIMW9uMjI+nBCh>@%)h z*&w{BT)k81SiT9VEA!5_y=u3DjAQ+t6)czjnAyI*!mg0^fE%2-ob=f?a$uY2d%Sr8 zgdNnEo#aZSrStl1hR34;l7QDNtEo1^7gr!(5L7(W4{lLNez*mUr zftbXB=x{rtzNoYMxg;k6=a<;*N5*C<}CLx4g zH+&w|`IGGIv?h+Iocr|7sR3I{_I7{55S52S!zqH9V7hib3pVmi+d)3&PcWl?;YaQ* zhQg_)Rtid)GSzzK)WY(*YVW$mub$p4b1ab{ooz0>_}fEl#+G>hl4)$pd!Cl}v}6w) zKC!FAQE1EuvU9S-Q#O_sA|-)NCQ=Vdde;z7ePe4}iH==_K}Agf+62;Y(G|UBc~dI2 z;Z(Fi8$0mq*|Tp_z2Bxr7UFNTV>V5iNV%ArTHTB0buHM!PAT&6y*SoF18bm__)A=8 zmdrBD^1se+Y^?Z=cC}7jp|=^FyIpK-S6Xd4X%kqc1%oKN?A^Do;8+<2DZRXC+l2kz z;oJ?V``fCpCQFxr6 znr8MYX0J_udhgs&Vyv~a23u)nc9w9v^ny<9u`0h4iI+1nf=DR!V_C-flCm-Aw};zx zdWB#?{ArKsZn7VxET>%B|2cog@GkjY)@NEq-IH0n!A-q9XlWW1ZpQ5#L*=J82wC4e zf}FlLTIjPff97x=i}XR=GBX*Z{B9nF?elz5(j67lVYmW>2%WOacDt66){O2{V8QhSu%uY!oYf%zwcl;m?1U2YmeZZ?aevy^am}N;nYx5BPkrbC*E9r9pLXf^1T`f2bdTfjq}#7AgPo zQ78ZX;H;Dn^htdCGSczJEe;UTJx3g6Q?Q^jQatTHIV)Pq&|KO1MTJssOu_R{b94ix z#AqXwa8-o$YT(hSHtSURFHkyaC*Kw(^u%;jVl5)+olL|CdDaCSP-8X$AwiCL?CnDwf#dBB`S=8i0h!I=HcoNTdNu z*j5xj30hT*l?=UVM+tOZY z6YD=;AiqZkcd*p;6Yh*o?>a8H1;plGyU8M$&+TuB`zvQCNag4HB~Y}-?dab{8K3<~ za#?0Tmv4dL_EY$kQrC#WrSftcX>MWy90K!`iY`AJd}HA&3uUbSb3OUohR{OHn>6_J zXKF5jaqO7{cCGsDpw9;pjiJ*9;CkjJdV4#Jz?w*9!=SzL@-)5j*@8y1G38lpY~vS> zNiU%eTi9^*gXcLZslk3Z-6Yix?`M2^G}w!)1tfL}1o-)#nN`w@~l}yZqhnS$X?svlFD4o%e zJ)sF0$D&;PvwbH|8iM|A4+e-C4i9jva)+Py@rI@l-F&4gg>E4`f|1bfkFUJB{&V(V zgehK>A0BFFCxMnkCstY8k#gxY0!v|+f0-_Twmd4UbKaIFa`MXONz{I}#%WsVAe|S4 z8G!82T;=n%Xsa&qr}cDKSHKqJpTa@wG@g0TE!yFEri+rB1>yxD)07# zl#~*5?heLLx=5`z|7f&3z%dc}IkTg6;Jtg(U<$Jzc8oAz0ADstk&V5*eL8KT1tP6~ z{2n~M8VauyKWp2sBZ=Rw!4qK#!)UEvAEx0x9~d^|#`=^ctin5LSteY0ltJpBUJgIQ zhM>q2%yo5Qa|b|ROyd|=Hb(&Z=J}3tN0f>;1xpt}KmySOx?2A^qLTTYXdC#R&FMUj zy{{u-r<8UXu6i-sVT4p`0N1^{Kci>pPtx673b63H{3>a$A*|2(5z=RbJWSYn;^`MH|fOaU~?L5x5k&qyA=9xkIi4si`B-9(9Q%H9i%qM6Qij1Dqyxnfo@F7}V zqqL^pe2i6JVzN1oRQ*XDjFz!X@F+M-k|R>A(*w;$TA7{E78^m^W;KqUtXM3QkYWY3 zxiFUnu6*Ue!rSq^*KgS1$SC_&veE_6R)(mfb@zN9y@#X>t|fZcts+WjRVH~}Qrz_` zs1Fuk{AK>v0ZB(c8+;$B+-WDBOgiSsZ>4Ivl%#tXCpe4iA&grv-Sx8@CBOaU{rmGE z`}4tB^d?0zha}iO_iZ5|I&^Ic>NE57++bjMALT2@X>Dm9GQ!h=RDfS4_CT=S`WY56 zHzVOn=sRbIN`X+TGGXDL7^U(E;TI}*h?bUrWy|lmp118N2e9r zcd4T3Kp@~J$|u4~0<_vve`)sKMk}F23M|gf9L}~8F0*7u`i}z&GqK|6T$%zG+#$)Q zK@8S4*@KkzB!r6VuP}rww3515;baq+bbdtNQGa@NILY!+G5LW~=pku2{bE98ste7z zk#exf*!c)^nu6b!v8ef`Q0~1CCrB9>pG3~JfLq|$f>-(3Ksa%{^kWxS(lzzht~F-q zIDh@#bFD}k!`Mk+{cV_;_-ST}tT1*gpO{z$K{%Wj)m*o5jH|h^Q!~SgDkuYu6%W7w6Ta|&I z43TOdW#=VrV(m7)MQxzt{a=3YyGcg2H7p4;iL#Zgx8%XwoSvDp>0)Cje5z!2_X>&c z0Hnr0+{0FkA!rwpQz6tAe-a$Yh=vyu4+WuOJe<8)2twr1qvGKG!;z8x?X8>y4Uz3D9;Q?NScI|!9h24B4VRr-f!=Y=B{#nl<;%>D!^&@1xx!89 z>LkJq>rjd;XxJ9FevII4`B#%*cz<+!Tu7 z3#9-#I|fUt#aYz<1Spq)Gyv~YGSJ<1q$z?3)l7L_DOkO*Xs+1*f$y07I)p% zK}5y61a=+2b9t{#&a)LxZV|HoY3c7GpHgbLx;_%PPIP+Wsuy9Rl+zs#Im|v>w51A> z3`mihO2^A$WuMD^+YMc@P?7=q#VlMTqPk{PU&U`>i5&@=Nc3h{=szIPeYfPn<9nH# zQR)9CxQrRyXp5EA6F@w8_?i_C)22*OCw5vd{lVNzrXHErC9v<=7r)Fnx_SF{>%tjI z_DY9yq3Et?{ru~>P;{<&hhc5`!50oI40IA+jMO>%TDCtsEz2FcpK57P!)6iI01Fa6 zfz3tlArCLbK~hq8D6dXHKrO>19rdeUg&WT-F307a;`q9DqBWr$o%k#l|7#d_I4gW( zb_$@6wc`qke{Z;-yD&WF1Pw4|M1#{PLsKsF5}Ka06!w$D2tWy8S)F^hio(kU>49I} zF1{aC{-LDhO7Iqoq%QPdBekO5sS?X-#wJ$&lz6DzU22yCZUSIVD=z1EX~UZsc68&| z7gBC#C&}gtn1uB%9(d(`lamCUSv=UxGbD=tdagq=&bhn!cNjiIe*xMTl-hKjKoy;P zMl7L)ru3S~mfswa5Iw(!Nphh8LQ6tW*cy6|_)>t>C2t%&_i~7f-ENhljQ=~*PgxSR~ z#&d!_kz0!_cjv7iuv0A`|ML-7bMcd|yDS}7oD44rym3G3Yy7UG!jSA(!MQY~T&gUA zvRlRyF9{1uHd4C-Rdvm*lSEM<&c0+xj!>lI>`9mS+`&mMO2@)GD2W1)Q_%sKU|jRc ze{z@A!tL~_B91Id#*qz^Agm-WBsc>VN0E9MA93N$?Zlefnz2H~%q|8mwjJmMTvk7- zN&4?`UyELhs5q6873|rs;#%%$w*>(=B_r_Xbms>H$4b$bBdIRGN-`7LJosYsLnG|) zeq7Ra;gZl{6i#qxcN$vl)`o19(;~!T;AWfw$Qj`YRH@9t_9>? zBK{ii1^*nZmS4k~Em&xJ_t+fMqd9ASKd`-JYMYtMC#h>_WdF7Ew$iC46}mfW7>C`b zSz5LbUlWrsFZgL89hv*Np2hafh(?p6riZHs`yp zl-vAJplH-Nta&PFtX%BUr07`U7&w-L4+oW%l}QpWYJ;yVmlln*mP~1;W!QqgEzzY3 z^F@Ub%wz7Bq9@CrWPUF7=*bI#NG#4>mBL@W!0K1Ox5B3$vJF&U^`N8tT(nPMZH`H& zOieA;>DSBMCOz{o8<_L`p@)B+<qx{nvr>hDQgA4~ISK2GWC*C!JcqHb1tif_yOfC)T9I4H zMk+SqoilTBEQ5|?9iHIQ2!yO3g1)N+_hD1q9*ex0*acl(R=_^al2YoL$;}y8-^>tc zym|^Q@n|3n;As1wCns*}Gt)h{l2%z8+$Z2t7_49vOy7eCOg#Y@-$8KvTFbS#Rimhd zRSFBGghBv8NZ$VP-%>v-HTeaUQXnUTi+hpE%zd;syt4S4A@R7xqSYs*hK5gzXI1^S zy+Ax=qM+<$fEJ-KmyaMttEJNE$1+fkt!y4ylx3xlOxTp)D^D=1N(CWtug>awl>2K- zk*d@&lyC7Dg}9jVWe+cJbvym60&Hcy)JO~Xk?T_9IwO8zJMlV1Yew+;Y?}@kuJDC8 z#OvH>J|e=6n-nkux49ljEH4!IK!*kgrKtM%ArfvWiL=4pWrJPuj#D5iwt>R6Bm7>G z%`G`YP1eT`yfUOg<_k%1pdA(xjJkOb#(HPjLtC@tQEg_b%kCBAoP~GqgJz?1|1*fv zU;^I!t@p-R&UZLI=*9penLx7uiG?xgQhG^dI9-WW47@nNbahh#+P6VhVq*H~70)zb zgF(#Lt^{h%Z@IwxVUPzOHPSM0MG8HT0)(zkv_tdnGIm=sI#)ZDpQmXzF?9arACE63 zmJlB#(~NdW@4+bLq%jyN0yzMb6qA}d+~a0aM9UTc4c=^tcq-yvM_44(ondWn^R4)(dK^2Z>^F> zHrs)b8HSpbpH29L-41jlxQ0{r?zaq|mIz{BWVeH0lfuTI-3J1#3=dKM#t;5ejFLz{ z;0~vhpdK+qf7FTwmqQvzb4AKLjGqQ>HJ>p+TfTcLdWLZa7^OHc!&!;q$-a zv(a~<+)7D6awKU1JYRL8J}4XG#YpD%dx$e?uxBTx3w@bfZUF93{k_+Pac?J#jKqYv zvRSd@9fJoiwwHp63xYo--S3tks)nupXM|GaK}T2v$szwULaFl5lF#3ZP`+^G1wMZN z)?Ct=&y(JtKJe+p=zX;Cy$GdBi;f8fmhZ7A@X%DVv*4 zO^v#`x&l$FBINS@koM86_LF&%PDX8J_hp6G+5=hk4Fyog+A0XRa2 zGC@mv@wv%D*i8cOfp_>-a?FO|Xy5#v<4P5{qhT{mA3P2VsId;9Kz@~?yDKtOitX?@ z9qRL)KYQk%d^vvab9$f8cVVw28Yh|TedDJ4KcbaG&fuu3HU^yKSUntRYU21Cu8_bk zN(JE+__D#-Gf-r=gPdAgo48i^QQ-Y%U>QLJdl-(#tJF}__pDm}u)WbCf(`*IA|1_0`xHVy{&fi9Xl8P^{QQqa;8-e-(&f#h z{>K68n8op{pzq>ml;RfZJ$mN>-WW5@*_QzAN4M`!B9bO}f|94)Nh5l#y~4HueOZy4 zBd;Ptl?Bky3sa;1%^dB1@cr5%k-6d(opzpIBefJZmPzN;=sj7JmNN@(m9XQ9l3$u; z{F}krbNTbfBzMekXPqkO9I-yJt~xQ}X)TAfSiep$0ELKEZl>-zfp_(0o%fq{BH$U2 zL&MNRCvlfr#e#*J5zXMu?!Ef+7pB`D4!R+d3NOoQZZX6~A$2Xk>GVRFg^WVrlRLz5 zDcciX9gwPbEix>+x_>u=W$)mLtdPS^#-9h%s1%)y0jE})u4+D{-ejLwTlHX*MPSuV z;R2u~sV(`LKk_)MJl|Q#)9XJDNP(SET(d_2b~~s$HZoxG9XVmVap9D}gV^L))GC!M#Lj_AN!=oyi*$f$sPbe}jR1fdkqppVfS$Z- zj|Hf`m0iQ76o|meMo06zs#X1;i6V~V$jhtwg_vy*Uy+9aZn3hhL&L^&IVX#7NN)`f z{k%Q$O2l3V-J2`#zLqmg2W>Tj@---z43%6%u)+MvMHSz!J;*`miiY8Vc;N&|8Y`}x zu?^hPuvs%l3|5Rw)?xQk)|jYqdxjYaj=|(aZ(s9;>83}mTo71WkMAEI4^uH|69YD9 z7@AS!?I%T7*ilhxM?N|R_{IHP-?@imxm_$TByc%7uPXIxnuws_iemBhsJOiJpsaKnNr=dVO#s z++fd?o?xnY?@?EC0Byv+dzeg{n0PLaMejgGp~#a&hM5$}dX=)^-BI(ayJI#sVm3U5 zJ|=~*+4=>G>s~K*1Q>C>>z4DCcB9ETI22FNMB06H&3op`=H2n=7^X6KY8X28rRJi+9$_OPPOMmqla5WU2?ZjQQO(^&BcK%ql zE5wD=vlAG6yA?OTauf1RD6I(djj70X6xxLQnY>vieuB%YPrho>;));E9`3Wp?hMqP zPR4oB)UkxlxdbME`0|hs4L+1)Bx(E@`{!BMccEn!$R^xgJ@T0dO_Aq>G|?k3zaL3a7td#iTkVxX0L{*gw9Jwj)5$Xv zNjS&<^oyEk?;MTRh6kXn$G}DmjSv0pff#ZTj)S}uGT8>j_}Y>}k$?em8@#pr^BlV+ z=NpNX>Z6G0+k_~Rcl!Y_RF#^nF=Z7ZMU%Vdp(osyk!B(Hc-UU+hg%+PFFYPmVf2vt zlg!!O^POM9o-JN}E^*OdX{ssVyySY9d#1Uu!HtR%2fLMia+pibk7=}3?`v{kqMn{g zI=y)AIgZv|!c!DV-tNf8;sP!gHKy#0rYf`b50_a~J9Pxognb~b*8Kac3F=(VU{#MK)<6q%fNji0Pl>k?j;QHYsz{*85<{@+U2E$ZUSy5OQ`ica$YRejAeU?_kOiMx*E?o*t^q&|5WOS|k6H;Qm5w=3to@KJ z)xS75X_olm?7^D7(EtrYNcdX?i97FN(ZFK!^8GpqnJ~gcRQ@gUZ9y5H&zE%%Z#d#f zSo~i4OQix;SqIIRuXl|;JZSN^jRJDTdg3MpVm7^=7y)`nuqIV7Z9oemQkN%HOO|2+ zb*`%js$I^$7M}`P+KZnFi$-hf*KvLFJ5c*Ca<)Z7TI`oHE*+Z$;q6NAoo>B)MW#+k zeGbbsfZ%ejcG$?5WrtmF19U2YF}cTB?XzlSWldB*dQP^nx9ls0pouF`)c-SskMYe# z!*ZT>VFbQc&*G1pZVRzK70yB9Y1g&D`OWG^ zUFw?nmb=DimTICkc}wwwCkzd(pBym7?JSM41=9df47z6iHd(#dm|BOrrAY z9-r^lKF4q`%~tbqq=RXub9Q<(;9h8HDcEuhS{ z-cx2{a$Nul5y6y@%$1H<$w6MP!ZaUy6x-&lFUFB}%)x)QlA>kdmWTiyv>$WG*^;Tb zN{zfh0mrCT>xoGZkMWKJ7)fi#1W+Wj+b_V_uy{8<>4LZ2H0ZHu|o2Z`U?1cv_pc^E%a$_o8z)RogXB7=CKe z>(|xio;$m^Pvb)RQMqe6cc3 zt2!Y2G6#r~@BqT7@%~D#TKj1uyAExKyDvX}{P=_P_U+pj!c}3c1Y6|v4eP4*%?I?Gp#w_94&{f*!HCdSF7V0C!*qFF>~h3Y=Mgu2}}HS z2Rz(K9LntnFY*`9@4yz55mMH>)CpRLFHqN>vRhE#JNMr)&W;e$XcTa;$u0FItLNf6 z7?rr$CVF`a0HZr$QG+u$_t$+tYQZ86px@EFUr(Po6L#uU<*uCg_;_#IeQ(hm4sF=e!`-MF!3 zKnWj_6g{x<YB9R_5)T#J1+d=Y&l4I$JRiO6d* z6vypf^zgY}R9r0l*#+6z*&0}sOFMVp@^UH1AoTmOd;ZIDsLCCWi@ONf*Ab6hIJJ?5 zJI3h=s>i<$e6LcI0#^eAg9qt#m3>Z9Cas4j*oM<`-rJ?neSJ24!OY0U3ydxxzpO%y`B1AVU_$rEj&SSh`k-FZ^dL%(r) zt>WV1uHC(>Ewl=uDC_D9!-N3!k`b+}AC@B1`q|2HJ`Et|8TGvF?(Qx`vuimyZIH%v zHOuva2<7k5EzD6x>7l8kqHO_*n|+wLLNA7UDTH$Y`e~#R#_#@T!3GWJqBg3ow3hUI#QRTnU5+>?so$7)nk7iF{wcu+A?R zs|D4*?#4m|Vyt5>h)9&J$>uGFcRty!~1s)meGy}>BNDZE;_ zQdr=UWx;M8tNFC;v^u-p#g!aVcF<6_Z-jC2P4Do>3y|n-{7BFwt#Wa<|E`JfKu|kvN2RKk7zKPAcQBVG*e1 zhglFgguYg&s)_F=$Wq?eUSsl*fOE!r?qR>N;+}f=h$wO{*Ze2JCMqsH2qD9j;V;{lE!lg zZprUD1CW^XkaAFXFT;vUSx3%`7YC6SYwp;CwX&CS>^M+z2vXxONmy)|=meIBiG$cj~6!@(}#lNLpO}-T7TX`6n=b`CpU& z{rJB$ED_ETizHbtO(ND7tw=J`GWHtw?Bh1QGkUhQ-$PXR;LPVe^J~%1GKBSRdAC_d zefe9}XIIAuczNbKQPhpXVNt1C!mHw6J|A|^m;def$F=`2KOUu4nt0q)u9VcJD6Ou+ YmVF=oWZ&SHa;q_;CYVKiG5g#91ArCH3jhEB literal 0 HcmV?d00001 diff --git a/docs/language/learn-ql/go/cfg.dot b/docs/language/learn-ql/go/cfg.dot new file mode 100644 index 00000000000..47db3df4c57 --- /dev/null +++ b/docs/language/learn-ql/go/cfg.dot @@ -0,0 +1,8 @@ +digraph cfg { + graph [dpi=300]; + rankdir=LR; + "x := 0" -> "p != nil"; + "p != nil" -> "x = p.f"; + "p != nil" -> "return x"; + "x = p.f" -> "return x"; +} diff --git a/docs/language/learn-ql/go/cfg.png b/docs/language/learn-ql/go/cfg.png new file mode 100644 index 0000000000000000000000000000000000000000..1290dadb870ce59bc45f045da78a8efb4e515ee8 GIT binary patch literal 45148 zcmbTecRZK<`#$~(4J9j;hEaA&D0^oX*@f&CiOAlxNk&x2%*ZM;NspWo~Kc--&0Z(gtKdOpwRc^>C+9Oo6NuBy0m`~K|&0%7NAB{@w3VM`c+ zuxal$68sxBtuS}|-xf1vMLEI-@qdY>X%PehGvTzHjJA91#8)>1x{mIxlgGGAS>(0l z$Yf4(GT$|6-Ihe7E)%em?!Z`^GOc;V9s!}e6l-eb>vPwS-QC@q#e76l?vlbLn%z6( zJ%8)FZ$!luulyoucC~U_^4aJ+;dIe;M6c8EV!X(R$ZUK2`Te+szn9XMEp40r`wQXS z2D9nb|Nh1-6P8Q*-(SL*l{)|D=ai^fC;s~n1lDb|uK)8FS~7C6|M?5~^_vX;{l%Y5 zrkwJ>zer#IfB2e!ga6&=+$)1CXV0G1($X?FH@CApcIQLJvu73sT`n#zLy`|4J}jrQ z$kWZt%&g##Q|)MNWxep=;ltf@bggY|dfbn0-@YAXw1q(MSCRgEL(-4(x+cQI!;}78 z_yZM_qipa|G( zXlU3}iHBpBAASD(xpvjx=aeWPoRaijoSgsJv+%ojy^;-C~wz6>R)~(dkRBgo$ zJ?=fqYHAJD#LK!dQRc>$o&17=?2lZWozp|GUeezG_8^QO4^~`U93364r>BQM;Ogq? znwy)`u3|g&`0-=eJCp+bCme^ANJ&XE2N7!2NRaS)6dldg z+@D1zARw?OC^aMFbaE5cCR&BP__T(G#_7|63dwD)tq#Qo`ElufRs9Zl{sRXN#5{g1 z$B^>mNq_Zy7OAD72pSdz@97$j4|k|^G&E@DWDp${gnzqVGrhjHfRUtAcO5TWxbW%IC;STw$?Opu8=FpBS8O3RRD&zD%)!XRW9beR z)7_vTWn5>@c=`%&xxr^qO|7rr!)N}nvzvICcCKm?B#YN+;*w~0({7f$*8aRMh1m4*@u87dK16wE25X^{V^r$B#LvMo^1U|lxba)>m3f5ikLDT9qepwX zx*v{?i5=-V2Nvp*N+x8Da7>dOD_(V^8I% zh|A3ugHSn)?wQc_;IawR@K{^`@F1LU+=@0)+uLps!<_)BMJXVBi` zM#YY)>FMc%aX9NzD-#7=T2F;VM51G2f;dj~Rb4D#lJJzH(Da=hZBks33SpG!uC2XX zA1ktF&z^xmYAnOQMflY>^@`H@5_=*X!4>JIinU;^N{eb{TJ<8}G31eQT(t)$%_6<;$0E-@e_khr6+@ zZMQy(P-EJ^EZoSod-v`%)i_a?F>M^fttEQ;`d*%%_$WNqW7V{vW8$O7kZ^HALIVOu z-R~8=d9#YmTU}i>Ff{y*9ou(^K&Te~mv1Bw3kb|1Nu;SIT(P#cwr9da+uQ%fEhqEG zea3PG1_t)`_eb&=9^vG)wihBLy@9yPF({^WS|K4w+y5&RiFSxqQ&UsLkb^a!Kik?f z9X)!KiHXVH-X2+>@Aek6%E2jQ>-q$#jgbVuM-LvnD5i?2iIwzuT~=0>m31_thR*3G zaA*F_x;% z=QhQ@e8=yIF&!++T@i7lntlIL&1wVE_>Jq=53{g%h{sQ!mzS>;aT;D+S~?rezd53G z-mn}Yx<&FgLwb;oDDKSPY zDkf%SW#zch8(l?3#m{-ySP?sVN=nr@bXi$hw~BC{Jv=<@zP(wBP?Mzbv&BP}{(VS) z$>6F%!&eTb$QJwd?JL(u!Mk&(D)U?xyITA`F5@Q>C>SFR2^(t*y;_=@H;bBo%yt!6 z*?)cA_VJ^_YThP-|H)H-6VEayPb9v#%do`N(#mRwJ@Ult!h&&$>rYgv3Z?@}8LwWw zN=!_=+>w2?*x=e(XHg#<=$@B$2gF>t*@&M+_irPYlf>M9Ju@y_&na7{{bpfiHt_p* z=xNf#o^NkFcG1!{e@kJ*QNYp{=I7J;A^9;M`}Z_&*?4%aAb}uY%3~x^bDrxLd3t!5 zo+2MD#vbegHLSYXGku|&7F_I5@|Z+GNZlw*<@l&iPPV_9`ELa6$hvT8KxTX$p|BEgcxu&c(> zA3P{-)5>{<1jXj`jlb!s`dMsj?CzuI#oZ^R6TiND*H`lUt$v=_=Ag!$#t=+_@+4k>gwpuVSNm$ou(you*kRqG>-eLcq8k6oL8B6|mk$l}ujt_O0P2?Sb_zgZ|updnrYKdaPR}XvnQt;e0AcR8o=YJrj z#n#ZOl^5 z3kww_=rRcr5s%MNeE09)*WQeKAGpK#2P`vJeyXj-L1bcJsOuF5@@q*`Q;QY8pP5eZ zOe!oC02JWm%>~@EO=De1p5VM%y!h1YtoO|DPQT=|w2`J{ zMZQvYrIHsfULe(u3=K^RA%n+D`drY`iooX*q{SVaa0>)NN;4`E0|UcSfy?&o+x=Fj zs#29B!=97wGch-hc=Tv^aPUK~`{2i&ii%ZkzrShh-i_zp>iGx$`_GE_t}Y^<2p^>E z;x~Eck3yMb#!wy4q8Rebu;fwQ#fW2Dwrml)@+CJf?+Nb_z)-H)zg@(o=I-v-=2am8 zKr>e3>?%=V;o;Y98LC;XJ4|{~i;-smc zpWpUm66%6Sj~=lpKZ*s4wl(FCe)8nWj=el7#Je4J`CA(NQ;^P;A90iK*ukPtw|h78 z_~_W!8QjtX)IMXMxwdPhTdVhoh!i8PJiWZM=&`=DJQRUAUO4GRrXRMf+s2{7-rBJ@ z?D>tif$vSo06n*C2|sp_(yG7wR#Q_GodSNibce*BE=)RUZK{eXODBh22OS3S>wf)G zHB};nn;>;ctOaK({0RjQpk zQCm_4j}U6GTf=oRdl?y3U+U`XbFi{x(S; zE`(KjijRL_Wo-4M*;!|mI0^zY>A%_?*wWoSHZrmRgqv?!d3QGw=Tlx*LJjNj<4lam z;EN9V-)DccaHz&6;$IU+MgFa3;7slDGTYAFYX%HbzTURB+(?x8fz$H?l{;{-ySp!# zojZN{NB@UAQT~7)o`?QMO!#-4AVEPvV4jN1_;@25n(JA9XLEJyWMrFUlm#<%Y%ly=y@zdW^j^qKF(mJr)f2bfgH$5}+ z%$YNX&j$qs0XCr~t6WkC5IdXx_j_rFkf+Y7sqW=B+Joos`C$6{g=DYdbBVuQC6rCP#g`9V3bU1AR}>mK6mu*zS#@(cN` z`h6}U_tK?HIPt9toB59)Ib!ppId${q&3`)3oWw+bzwyzgp-c&4ZXthe*Q@cvA9jHCl%{6*jT@vM zuFG>B#=m=tLc7DHhvUTDuHcBC+;0bnfu&*Y0b=<+Huh<7D&U-GoRO|B+B)g84-8wI zoB3^8(diFjNzJlFpvUYhnCW3`Lp$dWIwd_7|)&OCz#3*|zF`?y~I zO}`d|(UR3ja?1~_OKjfUO&r7qsSTCvw>~R^!opF1?)JdHupE<@muF*T4a*X9oxtuq ze^BOO|+ShyTLXk&iq?Y&PVs})9l_YpM9nK1$mb!b>Zl!HNU=M za?{NMmy`R0-sGmDcn@#KZHuxQ)JK7MWtkHoDfAu zkWTsarC8Qw+u?;eq291sFcBzkbX!o^4gWDd>KSj}N{Wle8XzQ(JuM*Pb6=WfYdaM1 zWvC_sL8X`-FYXauZi4$%{a<5K%` zeJ~(@z9sI?-xQ?&W1_2IC?AI@JDca$d+FXLMNJ(XP-4^PsH|Lzs+JxMI!l!NZ^=wl zv9x5{aNadDT$jvCKdOc1GJ{g)AiB=QwD`rD1}QEI)JM^O1vXIy7*APwN8Yn%&&0jv zZEXfOO`+BQigpwTc<}%rB5|)zN3a8Fa~(Yz6CLg0=?Od+U3W3)@NERWhWK-`$5MWh z#Rr*~8l;4H{(m^>&kry&G<}nN7icCfil;h&$42MQJ^UuQdGjswP0iLXRu+EO*47pk zH$2lTNcUwp{J!5I+o)93XW1Fu9O~WB$VfyCntxu0zIQth2m%o@A3vUxmp6slj?55! z!YZV&&;|WOL+G#m{`VWo!;ZzP`nNW=BLPWBrL#tfx@5-29?bjl<;&`56APY>;9vib z6618*Sod-CKq+qB+TObfw1XkpUDIn85w;8_l0(6qQCzt&?fSiqn5IAP(p&Sw6rt|eoQDL{Y6nxna9jU zDsx_3-&u0ov;zVIPg8|*9>Pc2+1gg0Tc-kzsKhP0A*D<_Duld@>}=Gh;VJhD8*lG7 z$;m8*hvt$%tAIs8k_$fujt>nI#m9{j%lPPM5s+g0g9U-CQ0F9v;ODX)9DRFezyO{LjSCpI%3gh{o|ypSG7MAlptsvAQ&p5cnMo0GI^z15^Zp zH{D-6L=ea?D5zl#dGqE?TpUB;)GW`569q_h(?xW9_9!SS?wHs^OM5E02|3mN+ncVV zU9WMH+<2LbdIasdTYrWb7#IL!_^r+9u&}UPJBv~{h&&*0@}%IEFZ2fv=!1{b)TCu# z`1#`pSFROyKHsudPP;*Mcq*;@#EBDJ_sIT_@K#V&r7X5JGdq0zxSA<%Qs3CvYn!$s z>yMax7q69Z=y-dt0?lK`?z1Q^FZ@3KYq6rTuCA`CY9z+~EnwZNcTeqlUe?8lEufD9 z*Ay>&H3`d^ot<4!FoUxMa)V{^QT3-!hkXqj&kYX`4>?}FdKHY)t@lV3R{v5(YoA&t z;_+U&lH3UT^5Ng-ABBZcV==fp+S}14O}mRrNtH?ROJt+%mJSLHZ76mcIeGHrO*f-l zlWPv1zb5-XByCrH8XXmttIO>;2e|n6(Er07>VqIPhVrAM_uaZ55c2pj@o5(IfsmzV z?Jod1Vto;DZ~QiV?Z+cZiC-@Uutv8%B$43A;c{o)ev+#wy1kZ+fUV*oxF#a!>bH@SKH_V%RaTw|AE1Loz zHU7t92q5%pEW!S4XQ8>FS8x%XZ)lli`Au@51no)|d9tUOeN3l!##JTkQY1EAHUDMa z8&ZaCU%sfAvJPDBd$$Svx8ocz0Qz*gk1WR&z}S?XQR&)b2+}}~=jf3m|JTF6ZU3HT zT;_XJC!1BrL;M?Jdim7T{5!LAb4xmwC10M5PEy@?_>*Q7-Oi?esTUoR z$G1Eeje05eshS85B4&4K zIxTwbTO@)axu*a7EPVL#CDy=qYG5?I^|H z#=w97DtXD{$NTkuS`>lb0Z_Yq=@NsmgTL)+mDGCw=%`Y*ppejU!`Bb01~q6BQwDRU zgq(&|zz%P}abFYM4#Bg(f^$p=!G2;fkuk=A2^_F%6k~(-Sh`4sYdG;pdx;Z zk4OA;7G1;1LF`#5YiepbI5;$f3fpzRI8Q@8O3SGVkTK*aEloIQs#J*T7*RV|6`IBa zs&(`qN#oDI`r&}(anp{@&e8Gl+J1-FxVW{|RkD{CbalNKzPha*17lHBSGU{PyP5gu z(Vz)aA+(fO@S-9s)T(U55~LB(IFn6jmIYlT;CYToY|}~ty|vz3lX5zO^A9}u@8nVV zt$&A7z%R(|j6Mrm4ELU+tgI<@4EPWeOH27|!ILMs0V!+0-#scl2KGOHkm03$uPQgX zA#@{eO1~0!31}5}wK`pUJi&MQ2b2Oa-)@K)*B(I@QLQ-o5bIFgp`6yjcX=zpU;DrM z{2?KCWwKw^z~G=u-fTWvKU(>5L^$Z<=3z!4!fCm^Rpr%Ti1dGM>mEU63%|@@C ze+*OxRZN51xM*Y3{Vg68M$WTmtdI2d^?}Ke;6#P5=;=jE2fZ_Rkv|0Pc?kV6+eRZe z#xUJ~)TgD&*|Unl`{lFaiRj(LvkChEy8KIb_nG7-)UD3<@!;17(->6Cj5k_>)ag?j@S7%5<)&jXRLs1p+t1A$Gnb7OUBhU6HU+_<~C-IMO( z>wCw)f0sAqMcVTCcLxuL8xqub?%cVf?821?BmnLZY^VoFDjYsJbCAx?&d!F0aqsF6 zQgR3i&Nn`h{lo78`b%AIe^yXXK^r?Mx47KvtE93Z+cY}kE zadI;2lr0YI*nWeEr;>Lqto?y3oFFHxY;9FSg2X{{z44ey-m>arBmDg~R(dUtpXicKYgr;L3sK1j|SX4S&-P0|Ic>;oPxGu z)giL@_fwzQoG{&bcp5!N#0@``i*IFqIZ!0+l(5~W|Fy+*F#?zOY>*`q^CB`z^=)t! zh`ER?ti9|@N`my=#5-}U0}jGiP4oz;`S>T0&CZ=W5fAtS6dZsJ$O%LBLz&2Hehq$R z=OCj3T|ub(qj{c|m6gR0K&rq|Ffxk2-m!(ycmVxYCMfr;tjm8cWP2AEfzYa~XU~Ql zi{+jy0B8;mUtCwD@#3eaz}Kz2LQqAIzp@geB`bU5y$SR@zGxNP5pE6t9fSe|u&Zws z{ND~ED3M#)bdr;kK%ey%q5bsf?b`3>&z&m-Tl(TfYe&b7R3`o-xLtNq0eAYIRZULtjCIz*lk{ZoZ85#xX=s3{%`T6)K{)|7MUBE@uddtWy z1}bFH84TK^HNg)FIZk#q1wlPb3-MubV<#t798%{+FDIp zZZ5B}vGILInhG?dQ&BjCNK}EAY;38ZHqa^9$dZI@M=+uFCVoA>6<^=baGaal8=aes z%%%-#Aujo}mcVZ!ct7cL+_>FerJfc>iopm{~M*?(SJTl;n)&?7+<0Vk zbVgcQ$5Ay(qO`#G>gwR_n3w~_uRUgntdAx=mA?hl3t*)~YFgwz^Curxn$ZYF)kK`z zwQHA?lM~=frtEkL9_THS0tYB@kLe-kOrFz2r(InIW9oi=l}*pc-~x8b$e=NAg$PYY zM^{aC4+qG>N+{ob*U#UklNM7Yplp)Hw0>`?G2unlQwZK~X=f*a;*1>u#a!k_wTaMt zSV~GtOl$?LQpNKi{8V^2?R`f0CE%L4zbM(-*l5C!%=g&Q(GhatkfhvM(f+FK56GTp zWwF?VP=A*X$k9r=o33PhJtQO~HTC;snI2Y`QCv4gk!&;tsaion!Pi-6fG%P5R+XBu zaoK^br5-a+A!Qc7HhF&?LEt>-A#Da*hr4*Z^p06|7Z;+;3f(L4oT1@YbT!-Q>^F~I zzM!w)Tj~`V7k4%`SrTa<_lspZEWxSa5+ba34mTSa2_BI{^?c25iGed^b$529J+0u^ zmN+ZXqw>F)8T!@#6;`I+Rhub8)gC z-H_+BEzk;yz~GAwh1Q2H?d^Li`?Po>l|Nf+yoUuNfHPHbmHYVd-!+GjBY*z<2|NiE z*Z%V5ApW0({JV7*tt>4i`djo_Hp8g1blHx2v+&}0)%{vC&JXX6MP6lQ-sM);yl~-6 zD-UQEmhF$X(NX;pL{1%8-#X<4MfYc1&8C1>2u8W+^sY!5Kwig*Bl$XYo04I<$>Ruc zDb(dtpiewq+Mnrtr6grN5kiQYa zl$_mYbF(JpotC4DCwY09>ov$PUc9KnUZ4}dkBr%Lfd(}RxfQXcrlJBsWoKhEHg*C8 zMO0MOHo6;t?%_l6sW{>wQ%O=6AZdZ-Dp}U%-cyS_+SGIvlW1yTVPS3ES?1@*#bDjr*{Q3oEvNk*NsBden&$fw z=<~*(ey{M!<>lqjz9u^Jh^7qz8#+W*$@@HcNpLZmj$3jiqQk<_HJRSzk^`u!v z0IG>u+q-wn$Byk>Td@3qP#|MJ;F!C5_~U=B9FDpX?tNYpf+X~T>;4|L^4hz~rI+&zp>rII|;MR6Y1TjhZ#)4l6 zR<%HCffeSEXFIh#UqFIS=8Bz@(+R)bQqxvKXX0SS>F(^Lu7Rn=3z&wcVuv(D4ImJ( zQ3E16(C;8pbL=A4P{mM2wxSRwDM>-WJsCFpa#8;Q{wIsPSAG@|Iee^H6sU;ceJ5_e znQU)tgj|fCi5Vh8fD!-*dS1XD+!hGCWUz#;$#M^2T#^=YFngjF_Y|ZdHe~&RZ-t|g z5hKh$>iyBqq+h7 zz+MGw7lfOILRPw%I&`bRi@54OeLAD2_It?T!j>DRc6L7}h!@hW#b-rQW{vGTc0kJq zFT9J1DdFM6w$v(^J18J&qjVtovnbr-<>TAOXLd8)>d^xum@ELlP=6|pg%Ka5aLgF{ z#-S3`H##b8T22O^)r0HTzgfbg6A>ZnLIMNo%3knL7lZjff99`zK zv2pSe5avY4fNTKxi*w5KHQ~L9uCDIA141F3jTZr{LWRoEo74`@}S2=iZ z0FdwBJ~9KGgr+g@#5uF&Ivzs-3VL1>q$2QDk6|CeX_MQV_IWg!yaWXnKWAL*_#KPG zR7VXKCY2C4W*!q9TS#04-$i!nc07gbKMHH3yYUuSePnGO{mGo0RaQEo?L=V)Z5L-{ExaQD&0k-6qmP%}Knmc&s z1E6k5aBwLYOmA=RD$87Yira`g$l82}|1acZqb@i&@Jk5Ue^WVgW=us$_t>%LR|h}R zq;h@?VF)rhMu)XOTz@AZA#NXexdlHq`h@vM3O6@5>@^=5c|I!_*ChzI+KN+B$Wi3v zNBzDJ$^1eN~Tk*L_%FVV%^*a&2YfD>)doC6OjaW!+$x*G5-;JM-G0#f-U ztaj3(It(i$Dki2DBX|}RqAkt50Qz+slJoK!b&=pn&B{{gZc_1GJFRQM^%IaY2?vKJ0Tch8*~3)RObYrcM6g9KHzQ-8_}xe%Tero$d^ zFSmZXf(ipw3(aoK$xF0nGD)3{fP8ThU=XxBX8pyk+Np*7`|8 z%8sT49&zzi>>erv!vq%x2jpU5g#K(w1REL_gcan5dc^Q$_evzqIX|hPmox@rgSh zJkUXn^}>Z#((3ex(^s*z%*nxFw6>$6k=UZ(q*72(mAQs#)&4hSID}|q4gh*@fcJa$kt*0J zuw+DEuC(3Y}akShO;RnjeM)Q&j~vSIt7dMUkLQLvLhD! z(a1BLzFQ4Jy%0UD*av+3jQg8;S94x^BvW)av64Q^05?}v5BGp2h9maMw>OYi;kxa4 zACDA^P{FB&S;{I;*DNUP0)KceP8#-j8ztpirx8`J75KuTGV$o<5+dl8f>5GSh3?$C z_4Tb!N$KfRz=DYKQnSkK76%hU(W;BV0I0iv}Ragu!MuZ6I(yn z#_8Jh@@L;HeD5|>1C=0q_`k3z-`(Ykb4WZ)aDF>=M&j3kf@+iGgWyStR(ZPk zfmA~YS=n)@8l3g`*x1b?=td1-AYk1fdc;F_N`Hp5?}6t9PyiiTR1}I99v^^>bx5Y| z)&^AuEFBV54Z5KYpb?gI&>VZ5+?joG%#eNAvYUab)C~-{U&_L=1|;$h7L{Z#So&3> z`Pn!)?${#ZE};g1PnDx*@+TwO#r)P>92|K4lCi_+QRLl9KYVut5cM)zt#5Cihl+y+ zlujd-Sp;+%1PoVfJUYnv{GA{o;5GU7?OPNDov1o&j<^^Zzr7C=!(0WVzNM8FF%gj( zqXnZ3l}=2@Onfa_0GnX9NB97|UdSSkcnt5Zh~#Htoj*sPc>n%AQ1c%{F(g~GhkR9R z)vSUsJ}AJwej973>_2_3g&q`XZfLMak{wms8i#1{MyND4HlmEp&tG+L&@J^Ob|I?I zEXn_L7KhmHqxY?=um6>p9TtFg;iRyzI~eXbKP3;3;*t`vje~S5>_`-G@IZ!@Mz|18 z;m5J+c+`)*^l-QK*p~$sRPT+c^Ie|hnhI|EFyMwvvUumPIgT)H#}Od|NGs^3j#?t( z^fWY-YTCJx?Qg??ibagHzU|g+ndfj2_wV0tMyckU!fmRfshN+jMIi#e+y5LWjcDA% z2YBYm3M)MW>?7*Tn>XXcla~d}_>gM(G^1yp%u_l$1QMxI1lSV2Ilc z=e^OJPIw^T=>Ck(ZgHV(!v{+{uaGnPPi3$&I9&5{Ta&$}&p%YC_Ok_TM*bEI03IYJAp{NGv zH)Iq8EMX*L+rElf8VL_WTS2dya5fUPl^TwOH=c8uMZPYC@IEMDBzt9m0I`P2qS=Cz zem%}EvsoaclatM*rQZQo!8Mld%T+o&o>SJ|+Dfr~JH!R;s^*nW+j+nT1Zc~*1P~u4 zn7hEK&{o{ee=DlSqA5xK=hsP?0Dx&QK$Ifd93Kv5!pUg{rvnpRH#aCivNSYMCHPs} z+0`{PY``ZCh<3A=1K1-*&<;M$r=kk}JVf6;0;(sb*g!`IJv*I|wm896x{KZ|<7G=CXR2vto}i{}51 z=YWoiCCY#H=8ZSvhM~3G(ZS)B=iCtweij#23DdnaG^S`_SG~Y0VgKrIvN9;CS(Sm! z9v#!~K3I6g#KZyCUoeU;_Xu&*@JONv7V13w*wi$I)C3@@eTUrV6dYfeBN5~LE(Vb- zC51Kf!$eD`t>9JDiQm8NFJ0(<=SA;iha$-|RfdVCLt@9L$jymYzG!;*wg z`u%nlrH#CSdgSL%L!kbWtt8ZGVAs&ckiW@;9VumYdpeE-p!2KyjcrXiajTERrELX) zqNBYJq3;I#MWxZMYGXmG08+=vYiUgeyhev=}Rh;oRj2Q@!pL34%0yeEUKPh~6 z9L3}%D5I}lzuvx)y^rEHa-`=2>8+?ikXd?S_kQ{Kk)4MpWQ?#$bb6xe1iXKOX@ebA&0_mom!A{JfH>V&md0O-8TL9l9OAdCL~GcQ2QY=a7CKeVvcT;$b+|iC!IZ zfO4}v?sH=xsUE(g!BaPp(xuRZR_&mq+_Ro<_}V#x?t7-_c|*gq&SXe^g1o$=&5`6m zmH97TU7LG{Mf}n#T`lU{+HO?YxYpSS1mo{n~1H)OmJ7Z%hOlTzJ zuBM~%0D3zQj-qKW6g@13Nu$O_b&cMx?5r%%=DUPnpj$2K_3deFWNwxvolOEZJR2{r z*B1wc%zJiJBU5(Qq4fbb!?*|jWs7ks53?mbXRW>*jtr(APH!7?GJw`eOz@WFYc> zw+Hd@-;l}ELn!;oV9;yNHte~0{0dk$zqN5=O~ca77Mdu05H`ApU$~(n0u(MSEooPA z&LOW?YdRY;$gp#8DBfe~r9r?)dl&36t>HjK=ty{YIcp?FRZ7eKWhm{?m zt)`ZHGbk(JHVZEe}5zhoAr0?x=vUiZ=6$aBEE zF_ZK>7!U?I50P(H17ydQnUK_wkb10yS1FH}e*oA!IGc0ok_0g-0g5R6^EfrR3?-S9 ztLt#i*>C$+8BSNIkC~!$#Zjo}>x*%629)<}!2Az`emUDacnP7s+`X#LtbwwDP&sN) zS=rf%B>i}7l$BC%wH||zn5#5gu4ld5J7?B07y`q>jt#vYb1N$jjlmk|AZ-_AJVfJQ z3?-@?F8&0=ci$ZW9Xc=>K`SQ^ieUE}qdG?bhhnShAUzvYJhk+uF5Vfeo zT&}l|&n>BRj8M{kV_>lO466U)=cq%g=V4r?+O|zPM>I@ar?H`rS!v`OpIw~i0P1cK&NpiJm8xRzRN;sKrD}X;pbvVWg!q?pV2A=^lxx2U# zn$XDwLY(Tt!a|i#NqygO-wvZ&h4Yhp7wF`p`+(}5xfrK9sI8&7e}EUOC)VWC`}c<= zCF8p%39tW6#6g}c|7{n@(0=-AIf#$S^72!Ckr;mV7^m+yojp zH6=w|tWXbsuWEu8r+h)4o+q*d91sr2HFanb09ERHNIB_t?J~c7`RJ+$zmSlkYDy1A zcF&&QZEdeQGe7H@@ST@uHQ+xl0NQ{;T;E^_ijHvu7` zjrksXJJoLjpc_w*pH#3c{{@3Vd8OXP`dG+}N~YS4ity7u*UdZC_frwr@XFV__xYJc zVcA1hUcSMI!hyNdCur#p!&rAQ>+rY_%0RC|CCef6a<|i};6L0JSvJ_|pc? z)C;#w&r(xeKn(=0ZCxI&JD{ef)}M=h;w`2_R1Q*^p+SY!^<=+LN`C${d`ZXGMK2RI zzg_2KAa$2$tY(j#lK~RzNoARif#Wnv`SQaD58S=Hb|{)zTQC0h+t4>F`?l$I8jJ^^ zjmxd9f!v5ABQbSPMc-{Cu@miHubh8qUNa7cG^egk%{C>S0J8r%q<|f7b`wW;;RVQ) zCDm)`?1Wi?Q@rYM)25iQQG(n6o~?Xs)Y2tgNA0#Hj59bxIFbr-a%hs(*EB`>eOKN4 zrNDp~U%krL_Qc1)*?AWJ)SlI~4a@>^KBh361f2tD{~}rhytU`TFNU^FpYovv<}b#f z4o1FBEfM7s zcX``7FgV7iS=LPm$S^mR17W@)jvtRTO1r|4LvGBLulo!oRM|FA%ijn}W#>h%gXZRg z$nTlS<237+%dXH#78Mq39!->bi*1*2BH~kgl zN;*skxmYvLxr={8J-DgX2%@*rn3vK22yu*o-}3IeH2?P|w%^|9-Bl%c^1r@YV}Yyz z*@S4^_Z9f+Jp6gz!0wFnbX&|gpD{+u=wV`F67#_eJuwL>DVs$zMc7WvDbCEz?fzv3 z8_X6!V4xLw;~V@i!1Mu{$}y0_R8j9&+OqC9CFZ!N1QLbwkJF;_VCVu5`+#X+6aP?> zolUf|d9CRZ!k;~PVoD6dNLxs8eqdQ|T?-U2b;F)sb7Dc&9g>qi#md2f=Z@M~JB@P& z$DfM>3@dZzhJ!IMHl zQn0(jz#6pY*nSMSMqX)X{NW7N7_O536Ym%gD^$<7S5pYa5X*0WB);Ojx_aZ$JA^P% zXc2iYU+!5{PtVFCj^|{CRYd0Q*uI^1Q6V=sS6WIxj1%A&v@Qu#lV$BA7%J2m_A4bI z?)tX}f*Yw^V4SrC(+XKN`rXJWMMaLohp&${u4m=uh8<*W8>TR0fX>6Q7jka7nrz^t`|MAsCgb+@&> zJ$y4Y_pxIovwlxHFq)7%!eRjy`=~*fHUuGTZt3&^(l8^yTi8Bne%Tax&e@!~NJgtz z9#S>2=q)6FDBpKie=dgfQ*^-(m$pL%=C>Mm^xu%CYS?j5kN z1_QfN(t`(d7_pqUNq~3^kbPcTTb+S@R?=+xE`I0=UD-G}P7ENu+gz_Yf>*lh%ATM? zgwYoV5^8lVt---TmdWDr-m(o)<(2!klol4AbM9p^;BfBLUA+pOiM-h~O`p_i79x-C??CJ_u_ys141tr~n#g>+qR+Es0UBOesb&BQ0JSZKV zFNW_iK^nkC()67KE^-Ka@BO$zihxMH`zwG@dX$Gp73S3qiB$|pw|8`CG3-@J2gwO; zX|l`|QHLnWj==SALhmJ8@>?qW+q(e)u#Nv>hO^=_!2VrLdY=}dUhkIF4KWEU zT>F&VBUtmwoeI6&-9hFBjO&mvKL;ATz4HM3lDnaa2@*h&c5L#?Z*HFbCWQC=@K3-~y&> z9^)+qkbZh%oJp3iLm>HBSs6GJfNrGMcjf2PvoY8@GC{oE1x-3K)BR(xM}4@x6WU9; zl$d`#^X)3wx2A=bmzEeLJYSUZ?=O|tCNBZ^{j;m!jsdKGZ$0Pmgy!PYUHPzfK_~8)Iv55+)ewdn6FR{S_koay-pYAzyY$^RzH6Q!3Zda!1OY^W{Qxbi;euL29K%m3_#rb;hF01JRm|Dz3h8SQ8-@xVPaNK}! z3GOPsOU)^;t>k|vnq9YV$9QhoL6A!jJXhKBAniiod;)g@#-}yYUcc^cX_)~-X|W@y zQWQ>#$jH52ryeD-WHw=eUDuaTfT4EFri@^OYl{5V6>A%t?Nn4!t`oYjL2pfKOjZa6 zOq-saofv!bfms7D9I~~YK-Z2Wq-kLA<&V^gmIkhLcn#>R+?n&%@h%n+Tw3)0kf1P% zgSXURO>r7AHCl5PTp0+43IIMhuIcN-&$XL|5NaX7S9iR# z;K#11tryr4F3qCUj7mkv}5CJD^9a9X6O=^4-uRdoSX{4 zxMS06_8`$()?yxgX%Tu+D3hB*9k&YLM0>mIM6ajM;T@y3c({6CDYzfkeUFyIw+aUY zkUf!y`YghH3~`6m+e_2}_H})GrL#ZyqY3ZFP^L2LrX;9z<_i3MZip37uv!Oh0B7hJ z`yjE-|N1JH4~Qvz{DM_05-Ac}Px7^($cf=!0z3K32&3PZ*nUz7wZzFDH zZYj}xC*1CJ%!D#7#1_|HX8#!15j!I~NR%fdoCIG>Zxc3!r%?iDdA2B6AsMG^miR)E zJ~l$)CzKjA>x~bN{_)pF5jSig_lI({W8QUH1zBllw|&bcw3P#1{6@&(yPE*LX#^` zx8kV2X$YaCxOfRCO1%Mz9a1J|`V6UbFksS=uT8SgC-}i6JWu9b z`3fZh))D|Qc^nKS0)QN78+)a5GC^)5Iqr14`eq!$_UititgLa|=%tg76YHt`g*#z7!?cbK z*?#=|Q#0m=aEQZ!G!eq^9m>WWZ^rTb>VOAo6on&j)EWdvGR z0D8m$+%<|4KoJS(K#!{J@D~OJgEuTlmqo)>iU7MUP~Lq5d;Uznh*ALW>ci1)e$a%m&^j0dCv`LqlP);vSB8*#Tta475J%>6?wn!g9s%8auq< zMxzBY2Hf1w9*&SnuY%uSUR+EZhAf8VQ#KWsCQ}N$U}*`$9IrVt$GaM&^O0_#@;}kk zau$_fXD1p#@iqkMqy4qv=mY>`AUhYmspjT@WC7v}G8OUVci?z127!-_LF!Hx2`o~#GE5UCz?y)H z1t>3%L9<1i``|Spzz^FGqY7S>Ag@LA_+q*HRJRdmlvGtQm}?7b_qW!jCXczX-S=!a zhY!J!2agZYV~5*CuZedqGI9Js^#V08H#_@!E$z=!yFv4%b$?e*^w_@HKsrSgJdV_i zXYPAS!oUH9jvYBF+fyjj1&2 z>g*KvUZkD_@64_L@?NOcCc@%7vpmECj4gqlu29NhHfv8PE+iKlNHpFbJP*{0B`K2R zZfr+a3LXkKmztJ_skn$5i~ZoQ=;>h>u!K7gtQ;@85i}c+Gd{$?UJfN>_u_?mX%%;O z_k$9ibOM;M#{gvd4#no7@897{kV5*#ygzy%*afr|S@%HkhK#H3 zT*hv0^kispz%Y-)3QGxcCYA{QL=4GPZYbhcVb{QgxI-@KE%U?sNS3Dt6%hkSex|1V zNH0xwyZvz6XH`@txBJ6?{i7p?iF=Szt`DmVjlY6%%Z;YO%R0>gA`r=%ZQIXJFD&%F zxU|bg6`&jSl|)>M&=(2~ZR^hcvr98pZ@7*fiwg@gF*R-a)bjF(X=H3H_Qs(#R?2T3 zc>lsa>M#QQVO_7Tvg8d>H(?_{k{;nJh<<6;Gdw;X^cXB9aS{y=e<(00s30#-=Io9g zL3oYOtChWUf-zs=^F!bM=8~!D{n%I)J0&wSGzb-*cJMAtE-cuaZor8Jq7EU5j=%53 z1XF`m`uC>gxECqMzm82T8-0Kf_d>)62lL$i1et1P^;I_6I-3)Bw5-TU#QOLGGw-+;qkOXaU8z;)xSF?((;zNOx#%m7YC| zi;vGnOFS`7LQsO^4Wpp9)<1%ZJPudjLuLBHBc{lH!Y8NC%gPSoxp>Rp#KDS^tYRS%=-Hi%)YO`463o9q~|4^jUX~Ic&X+WmNWG15hAc4 zB9{zcd@dEFGZYMs0}oj};FThlaS419x-U$uOX5wD*alTw-1<%d|JT`>$K||!@BWccB$XtjNhO4YN`sO#7*d%cL$yg#h*XGDnoLQ?G?2D3L^R0Q zNJ3?b29ykuqKqLr?~m{Ad(P{;Ugxj#{IT~o?5F3sKli=vwXStt*V1U#m10fw#*CS? z!^?BU3NZcart&Rf!6{@*Lx#Kr*GP-2rDwycrR|<(DXe(h=76?|u)%mawfD+$E{=YM zP?=kTY9bkJV@*1Bja;J(@i<5CT|rRc2eNZggh?|F4edh;fqMcGN>>VNE$9rO8CorU z2M;#IY_a1=)s!6y0_{^?e7Fa@jmEfn8J(lMNoGlf0m1q7={FG#(}XWd`Rb?`{i>Q} zpw5Ui#XT%(!aA)vZIRJX-;Z|4e><}68Ql-Ki*zWQ?Cpb3T~*t=FQZ6T@GUCN(*Y9i zB_)-D3Zqy&wzPxP52H8UB`@&D-h&6f^8_(8a=V#V=Bld*?wcl;M3%U9>mT>#K7HrAouBE{4*$CO%X>!V zVP5&QrMCZ^OUTVusEygjRyFt-pdbTq^V>D= z%h)zJ+?5#N;ieN>K%;vO7t6`slA`l-aIgWTV{x8Du@BHFVQ2rE_s_3gIdDLsBfHztZX^zy;TiFN9bsoz+`b+1TBXa;xoCIL zyW6+T@8AC*_3rhGo6ChBQ<#(4XcLpCMMa?>RfENCrcW0x%0DlcdV3EZG^n<)ob-{r zMlpPh;!c8yq*J)MzP=yjSDMfwfRNMkWf!q5uj&gd(u-QQ9L^vF`A6Xz8^pxKY~E|P zJi9W_ZSFLWU6i4qAo0fjc2-vOdnS;ouDm2;#mAxt6lJ>i;9s>kS(n44p8{XVEGQ9^ zAdf3hEZZ)xZ67W}nm{BD=ysWH&zn(2azcS>e8JQwG^#5C9%#={N2{9hwr`YJF(%=tPvwl zvrahGh&ebpRdLPY-*xrf>(`X1R^B#pQHHGwJ?gr)rJgx69sI0n$OcJcsUpEhMMfrg zHFOfb;@1z)jtKrpB9Q}v!23_0aPJfz;ly2C*C?H>W}8CJythfGYpXT65s&)E*Z2LO zb7ZftecdxCwPAVu4>nk2=ugDHg*^QG#Ds#^+oWQ#ww`eF_w@;#HPm5|J$R(`9tU=K!O*PpgPNwpd_gOx8oETUn{N>9%JzRCxWd(hwzjU>mtLgn#gmoqKIG){>zj>NJkU6GT;v@M=I?Xr9&pj~ zs~d_~UfZe!lMQk+ro_a?hW`9nPZPjHXp}!yBB2h+iRyJSYZ1>zIN-KQ;=Kaq;PpyG zra}V~B;DaUcF>!emX)=yz0(k~aYN7;8P)RsIpc54ug&yxj9dhw=+yZIbcc3}@Psi3 zbo@{5=|NG6jvpLj#{2}hxNja9FOd$0E;{ZkLvbYmeWw78iw+akUPf|253x%6vPhZrot?Q zt!8Pmstu&yBVCeAeeT)P-V5>%XS`He*F$t4RE0F7t%WWwuIm1OU z2b(?2DrN&$VZfbg)brk4xT$@Y*HbHB%FR6#{kb(h1Cf~KpZY(mH0|$gAuX4yR7RBb zwmNgDfwi!a4A;LWNw$!*%fj&Oe(M1ixVYHT^JR<%2G5dGQsaOL^z;CVkgv)XOocdPCc7|eGocQ7@T3_yvOyc*q&J*n1Hk7=BTHQob>=Z9FQPR@8$M~&?FYCgEhL@+z_nK_! zQ1ljhQFo4ej2q~)yws+OB5;?X(jvXYeYvH#Z`WL2zmitqNF5yu3kwRlF#luR2*!Ts6|D_ql`W+7FDoRFUoe8*(ifamQN89EDAW>-vKbxs+Rg7 zRaY+R;NHCrEiKQ;?C>1t_CA24>bDMRk}0)pTB?B%Q!`by^6g<_e(^x^g4`xPK26$k zr_=zwVmiFzqw+HOguyAu!Ne9Em|<(X0?hK!%^^}mZ%9i@W?M|oQ@A}WDk>^0bR*uD z>>k|r!L6T=b`hf>xsZ7I>S}W9dXd;9rOz=0MBuN*75UDEXAzDcO4vG6T6O&Re(B~R zu1-`-m(1qQoEcrUZ|AZ(QMO;uSCND}C{Eu5=T*Lc|BEaS&$ma92p(Niljqj>AGD=C z1i1klKx{&K?hlkppy)P|#Mleet2+mdKLw$LCO0)0>jG?i%6^rky48QV0R3AuwVG>u zyIkRE#N&+0mrD^l$0aSmn$&C|Ar>U6v{Jb|%gQ7nGsDMU<>h4pLf$?wc$?F~&~{_I zjzl)Y8|sW94if2lhRWu$H1!7GV5vs#+BM}jEFQ$8CeWSeTmq89Ss=G~Qn&$HEoDJ- zQcenzQB+l{5Z+l=|Ji1-4h-eln^4;_+ZJO5!0~&Z6N`u1IzH z9O4uUTjCUSqtv1sB^)7$5zYbg>1@Cv;gJ&Aq3XmvTaH*PWP2ltCyE^c3e_paSH@Ah z5n?H??F0(&@AIT;TFQWDi(lLrHWlXDq?t`*0kb0>YJu{7>R9|ug)qgnj5by8@bv3l z+X?7CQ{62rLPSXkhL|6~dW=g?A9?C>q;gM5$sf;ZkH^H^r}7Jve*naNFKq6)#UoQr zOUwjI#3Pm`WwkK1Ur-uA1!bC_pXGYX~e-@A7R zZ^pmInhoQF!A*UYsazhv`cpgu#S<}#eB5?4^z5@xLth$MKs_V^D_Bv4xxO7PFad6A zZhOTYl{ZN4mV0KeUcJaAoC9o+{65>j?Z|H2vwy$$xA>7S*LUXZZf}SP4|g0aI7O;j z0t#3JeFZe5{yw?eMg+_qWN`$>Bg41TLd7-jkd{)cTR2l5Eu`8suA_ zzm+Oe-bC z8o3=1aFW>(!p$xbbMD;epQq8dSgkh<5p*BOE1w}=L>QA&dx+Fqdax0_W%{lYf!g@P zw`%1T^8xpYb?-iUw9j{W7_n?{+g&P&yd4p#&cn*rYL0B49_MORb7}m!(EQcbKeVJJ z70%OrnSQru;)YM#Qj0cR*{=f1b6IY2y}j7e%jl%M z^WinZZwiufVM*SmQFY3iEW01Md-ue3Z|+iVO~|XOCA$iDC9_2m(AL%_pzKqofX5cg z9xtBfSbtnPYK~5j!Q6Q!b=_kipY16>bMj<0F^I@7>reMqYu6eRJO?v}>QH?f`l!E) z50VOHX$AM=V?$RiU23`Bki`v_kv(|GDciGOiO&R`Hz>VC$zj`-!`Zd(P}ulZ#kr#=s4=ULoctW+&0( z_N}=2(EKsZ77gd=X0M!~(eRSIytwhkEV;h*+xBHl#=^nBrKYklDFUqhSOTtw!)`Z@ z8d%(rZHUPtWv_cs7=6DI7hRiQupDP*sL4M0@%vkgbLOwe##&WJya$XvQ!T~)F5lyn z(P!m(RnbXb5w_gY#RuWpttnsAg|*S>?&I=^GWw*nb-v+hq2xFGXa~Y;Tc?!z@4qNR z|541LXQfb{=UuDcPzs1#FyYgVvX|+z5$%5ewQf}XC^ARoaTva{MI}`Nl9qQx-PU)1RS0M`P=86KLCDY8I8<>V$1QM|J*u{G|D=K*fV61|E7eVBo;vReN~U z^h*EY29J@0HJ45a{am@Jy;beqm4#3FFp*{8p&cItBlmtbUUECz2i;z(=jy$Rg@BXDw~d_lj171yMQ{|n6mrhzYF6GQs(p`S!pevf9Lff(!8iLcCXKF>z9=u zPnD1FRWbaJY~8u8TJisT@s7-S5V9hucyi(H_9fawhn66{YH^%9_Ya!HNK>GNqKHjr z7Gw`cTnJzZP$aWhL?uakgxV6+kCpFumaOlVcJ}PsvF zAABIg=?vi*8O^Ktqgs7W<_~R+w|A`>eEJBwo96_5JPaqy=L- z(H<{49^AfHAg5it=#RFoF?iUqpRlfgkUgh9KX^O--O%zH)p)e`?DHsB6e_BfE7eKs z)t;r(JZx1yaj)&WQT;X_4p zdcr14UwrK+pc)w`4#PMfyy*xW;f85bp<)tV{rBS1=!is>!D9Ikt+`9(L`Odb)rNzL za%0!phrr>bjkJ;~k0PClW@z~pp6IK0n=*4kKHK_?iki~U*l67p6&>B*#YQpw#ggI| zE3UXlapqLWB&K`4X>9CVRiPhuMSe`fd)s(tW+aFt4qUjP7w*c9NA5#}gW?wl*M@fS z=ik5lWfvy28vrU^Hw`@fgyhTYL+Gh$=>d8vuU`z|a-o4xoJjtaqh%8F;?4T{e%~)1 z?~v^j-*GGJjotp!V-6bzHcQ%Z>89Svk_7t^(wL7q_-w$m?HTUMju7yWe~(3tCMjun zRlsHHcC6??j8)_MxA!LPiE-H8t}f_7>w-G})jgD>J!VYI-uLAHf{PvSZd#ALkzEzT z$-IEXWrn($a0O-@%2U)` z0nT2&+yGBEwcg&$kFu;?6TSWDiga29SFeBa)^r^zrJg%DOuX0G@&2b6Z4xj_e@Z-^Zi^{d;j8t?SI3q;!AR?>dJS-h0ri{*Cdpnt3b^n&~h;i=c9v0m4{F@$? z^1TZRTq#yU28&yF40^J~YG`&dnK9W+(M6~^w#RSgI*@WH-yH5JCZ}WAuzDqICT1y} zf3^8efK8Qb$>f*=z4j=gPxV>99;T;ylkibyuCJ~cGzqD(=DU+oR?Iu$Ii1`s zR-}73KmX`&9hWcGDf7FFjZO?1+U&AzaDBh&vW%2a9T?a@98o^6=NDHeky@cICCby% zzWx5-K6|l{hd@vF{4m@KiwUmVD&DK@;v6fh@YEOQh27cphs^{FTjlc3aG2!83m$nP>KeB2e}-i|co6i*#jfM5{09dg z{@7!XoF8+QbkZ-)dhI$@r|l8H=cRunbwqYQd`L%+9I4qmswQ)JADu7NXV~U4c^*H1 zejV|>MDE~jh^T^3sOpg8@@=Dg1a6cMBGh0ZV8nAHSH_>7*(j09KWXTodkZ@s)$c*N zhR>QS=5T%JIRj!ze#=Mk+98s4&@1?IJIqvT9vGg?B#r>*=j8`DYJT*q33T>qwHc0Ulp-BD3O1j2h7 z)90quG&c}HlX!%krw5dzB~HV~W5#S>qXfed-#EWdRemwJAj=z(+mIm-<7|q194Uht zH`Y@w$S2t8*u!_wS7?C+G0Vi)Hw#~$iMw;zs2)ks>>E1WjjiJXCoKp~{>t6JXMOjj z?vJZn#l=bH5b*Te%Hl{`XDJH92THYCH>&1>LNRoJA3Jl_taYGqyeoOaDCOfX zIu=<*o|~+u2hlbJMLbgIA{y#rmk}xD)1=rIt7Sl_SpVVa;dW_+TRjrbYW%_9TF|b! zI(c|#Ul$wG_Jdv#WvFBSgmxTXhSzMt+5LMD3V`GmK_jQ9H5HX&-_!ZDD(w}eJPt50 zj!GR64EGvvof&a8&{M5+9&2e;ektza^Hw|DRnP}D|9IzXf6?)UJKBWEo1)*mrqT3SJtWXhBm@VE-!52#-z zuWXZ1A8Bx!-pNbyJvqOs&P8&w3+4Qv??76>xewso$Je)57ka=dc=^Sfku^%IJewd4 z^qH~m7tN77T`$D|3B7s!S^(dlJ$tsu=0((V3bp$=q{k=i%#QA%WsmI$eFnUUAg=PE zK3y@5`j`S3rXF>+x9anITmWo4$qqR#95J(@d%TMC?r@X7IniB)2bQm*wku=hV=xm! z=U6s4DK#Bq@$TIj5%m1tJ((8KVJ)d5I_QyQTr`}%H9_qZ=**?E_-Qv#LR`a1rs3SF zHGTbx4{Mq1`d2Op*oH$w>1u`_eAB`UOG`=k9Wp^HpcLpR?AR{4aS%Z_{4s~m+TCZyR*(xe;;8p1j-3kRm0J`5eozu*uAH3?%tjHaM84%ZV?B$$oPAl9%Wf&Ef zjA8H^B+eeR8pp$$fcYZ;P8Agq4HNll;yd;>JYu)9%v4dNsJo)0t$!Ei1-BfCijwq+ zLr6A$nC7Dpwy?kdcM{*2@ONFd26Nq}q--<%6WTr|cF@($ve3OU0ApT)AC{U79#QT% zYZmyyZdWHn@jfQy?J);u}3QoR8RKMBZd4+#49q#d}quOKRJf7egmZ7@%qS&UYgt z9BI(beA0I^RA>IymhT^!Vz(Zcrcs)Gg#YYVPg-9{3Qlm%s_%4odfw@bYf<=%@$a}% z3CNFVCn$Ww&~hwhoGYheTe)oM(nxLln70r9?X_T*;IHyDWptM)T4@0RhCwAX*=NR$ zTR~MSSc7cRj3o#O<)K+6JEZW?AKQ_Ra-XAvdJ)R+8CY=MHMSJ=k{Pw6l1%r(-LkqC zcD>EdF#t(k6Jme zN*|^{B(bVhzp(t#quF$LzzFtGeZ&s?)_)utDV)Jjgn6!kr6% zx<;JOxae17R!U~Nu)YhVdCWB4(A0$DQo|7glIylb(iIpNu1LmMJV5F?#gS zuPjk^>zn~UFUzqid+TG|Xk5!ZFQq!abmsQ$sBvfdc&~eS63taX=Q0KZ>}R{9t>>Tk zA(roQH;x)aU&bvr8S&kU>C<=8zpC6S(cS08#Dz3>RFV>6V`EWE@)_)B5?ARRu6~+( z-^*{jnOP9{7ZoM%M$~@&bdt04kwY0Y$j1+J73S2~jzL$|5MRP6GdPm*PiA$oPQSA_ zz@<90q^9PId&|?A(W?hAWl-0(kQ@pw!N`%nQ9B_7Bp>Luc5Tc6Bi}Sm1(#*G zD;;j~;UCYU{{cN_nAxRlx?t&~?fLwa`#H=lIWte&i*NyOav0Bz*x0^4^S?jN z%+8)7Da;+iA9mXFB$;Fw2B^};{pzO@?kaS7zRG~cTQ58|T@^f@k}9&lq@9fo-dFgl zdaV0w4CG~F%JJb@$8Y-c^XraBv*0&3i;a(Oq;un;=4#zhC|WcvfPLcNP|!D!|4XWS*C4k2T!35t z344d=Q{W=;?Kd}ET3BO^kd*y>VO)97ioXTgKv%g2BtYOT3Dp6ecx;xT`c=-faKWn0 zp{bR&&feKMuW3f5B$5l8X`ND(vZCt?btx(VJOOkM*~K9S=urU)7ca*E1OrlC3zu8K zr6b%LxL&PG6igP23(I(;p@|)&eb8h`CajjM#~3mEP=+uvkclqB7~e)R`Sgg09*zCa z3;a;70`X7(sqOm;+a?;QPi9uB5a7N_nG8kTJJ_M{1J^#~ptt{&9DYK@5raM|Ki(l{ zDNKYR#+GN<(gfKqrNgWEw({L77?q-*kC61>}cYk|OlTO@ym{W8<3GKrw7gsy#I-Sz z5`D;5ffU7$h~Ffa*ERpf&6{{B)%%a(clSJk!lI95eqBr535vOpfS^FQ730db-EhMa zhZlq$T&TIO8fF9v4uG&Kl9R`2arLf1jV-bcuavgqq6^9W_Xb}Up2tH;+8>u4R3(AaOD2Kp*C&z5>Mx@^Z zg%S%o=k7-noT9})E$t<)W7f(S(FJ~@Cq^(u%j0}J~u#v9VTi=aT zP4qbNCAEz|)bRSXAch^6gp<4{br)b5cksXWJp^ks90l0Iq$`M|Z2fD9`V67jLq61Y zMF0Ad9@7mk9)H?5R(wahq0skL20v1nHezi~}IwY4cvhk=4u7w=!-rT+_v zl;@7ioyRSqgF~_hvPm8kX>7n4X-!S8?K2Ek4RY3q!#t8@pc(0$dEqX{%Qi{`)rM7R z+icO38%7{Ut9-(99*+-&Q46ckXh{i-P=9c8)WG%Y3s@J@o?HG=W7;f#w(xCYw(U}p zKdj(c1z>qOHy6ITv-pTs)R|_RzDd=Ac0_I8F88h9l&IOy-C%E%3lNu3c0k7mI-wUt zqD%s^D>4#SVeWJ+#|v*gc2(N1qbpTQnhcF3%x9!4e@OaA11ja>2apAUyKkr(Q|4}l z`6%gB%GP;Qbd;i4Re1cEz_>nqpKzGjbA1_wzuDSXG&Fm^3))k>q%ES)&!Tl90m(8mJNPX&Gf1`YKik@(QbmEu`wiR` z9;COz&!elzd|c~CeXfuZBe<#p9!pgmeNml7Cd%$q@GI);*`C*~ox`dynKdeCn*11} zgoy}Q`t<1oiy*Kt0#8V2Wv%#?DPs9#vm!VhDhFB2XD)t*Y3)&v+8+}$pSu}Hwm*h# zA!Y8P@ijhjVI;wxhSy-+eLniJX`WP8zE*k@J_yG$8m~6Cq2zwF3@?W5Sm5j|$WZw3 z)tmZZVMK_%a`|%3oBz{x)FP0uz3(3^pelZI{L6p}fpUZG^7hfAgI%lO*hckrtl0(- z?A{~HO;MqLf9rvJfAT&Dp3KbGZ6=}dXqObsIw)~y?FMgz*tEdTX2&HugV^c9v&_fa01`~Q9}p^k{M@f3$#KV6SKvv1+(W4&#{cRTvu9ga*fIY( z(A)6>lMEcL9cFW}7mg#S@ObJ|?kK8J&_QSCBo?0TCKTt`iH^&gY-cwL)kE~hquS@O zP9k>Z=svMxK45WFUlJ-V1(^5Cdi|5@F>V1745uSV<&l*;CQt_;kQl0|2`l6mae?~# zb^Ovv+oBI#rjo+OHFtw!!@1mCxZ~$eo$9$7x4eYRQ9C2)F%rY-kN>b&=(E0I-33GA zHq+W4?XrQ|Dv7;|KW_xZJ!!tLrYLhO|25=K>ul9<*MMGrna}^r1^6aY(bY{cJXQMs zgtn_{;jSsM(ED4}R`AykkJdl3EA?8duVT0>wMjs>M@M?}oo8$=IKTD}dRLq~wlaHW z`yh$MuA>-W7>MtwcsYnI!1;>+j{j*#E|2Rrv`u@H)AHo7>-lN{BWIWh&Tyb zKxTRWoRP$C_ES)Nrp}Nd|9E-|h~)u)!Bh`s-j<7sr-?;OPhgY_J{Jon{-wB<#oahO z{4h>Wfc9;9)|R9MV8O+yA$xTdcXDnaIrW~IlWe?(bY8Nr)=utD0v_RD)$8}Ft+n@2 zf95Dj#^h=`6&FLzwU=GfJ=DS8KHpklZ_>6!=$QG@t=?#e!ON%)W1hr{k|~M-K}^)t zj&VBZ)6PHd7A7tg7C;ux+ktW9ZT`hDD45G&U|t+BCdI{M=d)DUg51k^4mI~>zuzJi z`$9W`>-7A2S(!Iv`sB`k8Q{(UgDC^La4@ewIooe?*(lZhSk+Mr@!grEKtG)0ga+7! zUUE=JX3a**kEi4uBn$xGG}Fd&tX-GLX05;i$|CkLF?-^c4&>LvWZGOWb9O zbOSxq+BCGMMe5sclua1$ue8G{*~orcu~E@ICv6zD?}5e1QTqlK=}KuPFCur<%+M0Gie25jYwWSt%seZQ-^VL=8KCWjLK2>-T`-q>=*33+iet${VMW4mu=bK&imER)x6vdX(ecYST)a=$P zY1q!yu@?f0w~5{U@*+~Rn{$AKX3wbH!@)Zpca1FSp_{BVu(ndn*|&&7y&IA4m-R{Pa^ICK(%`hajyDti64^XL^}fO%^F7T$tlW{`?QO z8N#YI1G&5pG78$oMfLhf;w1fGS@~?Q)ve+^5|s+zw}u9{PMX{vsb-QLF?4>bhD4%f zL9A-P0~wWb+xpBcyi+>s_g$uogr!!tULBceZPmB5ZQJO?xi6pguDkh*Ta{)UnPBAn z38#_{t6sW%ne?J(2W9pNvJLV(Ev*J;duQj<=gvjH*L~~jt!#(`e#*B>&pZH?NxM{K#a>;=z10yP%uUa^& z>E2EpDhj#hu?Q8}=<6R5kTg8C>dR0W zQ)k!}D&%`t0Hyr=*0N*!WD+qbB=R$iJ+G*`_NYlC?ji+HsUt_H^ZD-C6$56h_}pA+ zyQN&tUE3j2KVYP1_nJ|wJp1R^Uyzv*XjMJti_F3I|BA+Bp&SB)d7PBW-3x!mDR+%p z-Dy`Q*M4uQMPH(_+K<8FBS!SvvQ~8TF`PmAB=>vgLk9(>yY;=geYCXTCXiLN5a2o> zAQvmNy5(Juws5Sis;NkktB6$_*(PHhCD>1_e9|D)b}HNv@T_anL>@_iz#$i47{VnE=MZ;aK5Qy%oX?FZJl9;Z+86B z3ksYqviu#tW0xpja!%5#=zaShar+Zbob!_7l9S!Q9pfIy;{OSxNwJyzCSDZ$*nnTF;^8||bw!luqKZDE`oyH9I<}63AbIMzwn#NSt}+{E$S*PH z;Q1PcDF^$hGLI8|NovAPVT52?_y#7<&PQGKtq;3%20}+qKMBAv|hl1Fe&)^b$ zJk!E^PGLFqEEXnd17u|d8Ts7q;^u=s(R#>oB%OgV0Z#m{uCl5L)ETr|mSu!+QnOu! z0ShG0y|lB8cjy+ZSd$lI=A(B8?Bq-ftR?d=xk++@{0PlI5F4JB)Fu+|ru}AwublN4 zGO}e5nF@1dL`S;;XaLvV=(WT}QETML%@~V_L8oJ-OiDgLIz92_ytLFA*Lq$IdmJi-?*diU-Vx`~gO6ZrF=KB9&pxU8f9Njr&z zG{4_ZR!a22XKZ0Pnm3YkGA-H;+>C|ND`;$R@l7rx3zA6q!p$lC6){;h;EGy-R&G&Ik?7%?p<-i8cT##+vX-C&~jJTjWN_kefNZ_ZJQpWuV||u-Q$|C;Ni$;0LFs3|&Ja#}lLFG07Cj zW1X+B*XtEsWR{b7!Qa9DIbhb3C7s}2_A^eJ;@6CbXT0aPxA$M-ty65Q;WHP4Fk?M= z;R|%C00t4!Lzh&NS{`%8Vt#;q{xMSwreBI{#-1dQFJmZERl|EpMm2dA5DPu zNOnRc;Lz@)YGhQy;N_7sfg|_E$76wPImbkl)t4^L(DKP2sXzFcPy{|3fr;Z$V!Y5=dc0`BeSks(MtVAor8X7@0x9Trz3W*1|ox#lQEp@DU3n zw9GF7IFL>@C~jp&!n0hTP`lMF9l~A+Hsgm;D-69(Ff^u;C4Uq$jpKy?I;$DhJf4CD z)?c^%aK+YakBY)R*ZgGwG#FfjRrBu#yR6!PtQ8B8;5Z0{l=ph_nO%iVT6TDBM6O;l zxR09ile0=FBB{O8esJ~}V0+XvykTeA_*;*=+-85X%Vaaxlm3vg>nwfG$Fi3==lX;j zlh{Td&w9#~DBB$Aq739E&}w^(hs0`GS-7 zK+foZ9;G=T)z!urlB&N7=={-GoH9@s5jlDu7dtuw1N#M89`}i;4$*kS^A!c_3+w=h zfP;kjc*sceHhq`=`UPp8mevVyP(F9?(f~*#tT`PO`{>x%S+i&F)4k~}Vc3~^?i|CS zHppuqDFdqV;rCt6i3PtUv%+`m*#A7@5U)kXaAxv>*!v#rDk#cv1*H2kY-i8loYS-! zNz9AA63CIsFIAoYiWttZ$gG=C1vK(02@$FXUUV0=z5p~sd86U}-pkv2^uk=#l=*W* z&OP<|=by~gbrT;I@34Zj(X+!s6e+k13gaZ+r$I5h%{^bZC-@Lt)?Dn9=rc6g+Sn+f zIb>6@_`x}-8}DL{4Y52eqQC`ZI$V@liv3uadkXKGn&7_5O#3ce1Dp%Q3apCx5y3cH z7@^RA5Oyho7d|&bnD3NhI@vj}jWB*c>b`mNH9S6Ptb<93wzWV@V%(mV-KKcZF;X*a zDapwFhLR9~pS^K#1qV#LMWweN_K?G-y#9bnt)0!*!TJRZVQWcdr&%okXX;?9ttP78}UVLk+jGa zdK=lm$YH}KnS!tp#2LdRvIQyy5vRTl-$*e)ktHY(|L!2>Y{Lc8+%h`(#0fv<&wz39 z`+PDDbL=DFlKVV!k}5ht{N{OV?SHF>xjNQ-)Z#<%k*m72v~;gP7XNk7CUSY7o;~9b zBYMKIr?#N&_F|DNXOgWZ7;scyW-nS>Sy|*ruhAPfZn}*Pp2p^;(3XHzsHj=hXD{1mE>1e;-op*wc$kY(?oF=8UA z6SD83%xK_C>du!RKJ4B|?an!V*Vs7p>JBkgZ4#55%uLWb3sYb&-Xy%6dBI1pP2u_> zyO?6?rC-Yoy_+}Ru(ZO*31I#M>Bk}%x;|?Qz>0`DI4@3jb>UM5YhW34nVn4oAS!{T z6l^#^%Gp!81-CO96UXMx_O>BSfZZ(jKBkj+i0zT{{JHb5DKcm375$*Jv3OVTogonD ziuaF9M{uFDAS>2xDlW)-(Olq&z5eQ!T9kcy9NIJjwbwb-U+A| zt7jIke-rM2EJ7bi$*qF~&bhhGf9A`s=Oe)myBcxB?M6vSUO*eO$rjLC!qZcxFL~@B zvn_!Z7Gmcg65q+P$;bOG)38|R8}f=rg$b4VQ!79sTx)vCsE|j~a6&Yo?za(j z{KP=TrpH|t^TqBmauR>-stJr~1RTQpBr^G^=x7x=lwgSYpwUm&p&pI-Ah7Xjqx=YZ@yzsODoj+>523?U6#k>VUH9KR1cWt3!Hzfjb3sVW_RlztS!ti!W2Da`+Cf> z@JdhVBhZvYGP?l%$x>30s#l#nc1%`Dsrk*D?sHnqe*q1>e*b_ux7t?G$+4JvbB&Aw#*>_lDiUF!q zlzI4n1n=b;^8`mxSPnNcOR7RJc!e62OVGi%dUr@oBP}+dU^{M%%dcaSshgxL|1G^AP0- z?S2yz6KKe4f3H;g(*!Jv`KxsFckh-yZ#HJkec%rUETgG9RV9+i;gX>gv`deU|!jWIuQ zha`D<@!^B?*Ac-Q!qbora$tdkJiCM}|eM-ln@ z-8)I!zN#8T?!`G?^C3Q-p9P8l!c4RL*zn=^>;xm_>dX?9RM-_)%}jkrDvrvf9CT+^ zzd@q(?~s_y%<@F35JID za{WYN*hu=*!V3-#hVb=ZGBj0m$buWMj52qSkb90uVT`Hx6b> z1Vc!LRwA|oQ^kb9C_2cSplJd=UWf{0<1I>OFe&28KJo76BcSlG@7vqk1=F1`d${2+ zH-t>6xivfZ=eEHgDCY%E!=K;A=VxJ-#_6NpN~bydd*?`&ZKnr`(|gIZ}VUz>$= z?5F5a!Hoj^L8?2w2`Irur4GKQc%%sY7vbj&h2kK)hXew11_{z0IYHNPpN3*H%2#YKs?BA0;%B zuq#6f9mK*q+5pY9eg5nWnsj$hw?KwrI-hszw)}-I;SC}x zn9LgpV1M40Yp@wK&v$9HrsyH~P&jF9ejV`Y9Uvt0El=rN2{-P{@_9_)M9= zE-)B7_PECIdwxPBEQ=dYH%|R46xFb8+c0VrHkk&@ST1ad-n}&|O>gK5lR#N8Hc#lV zS}y0gbHgJd42)0NEm*J-1|PQz>u^j%UszqCT)NK4LkhhK%eT2Gx-VaTk^B=$`i_aZ zq6J8mWf+vhaezv*b|PZyDhxc;CWl8()J=?BR7h0^K>;wOTaO;G6LZN2tgTCc8_Zpe z^LNoYVM)Jo)=~-^3Euo{&Plk#H1nryFObq1T=pq(iHhO0>v1~`;zQ${ysx;sh{1^} za&n(4%sR0Gk5y*&2tdBHgv49yTX+O~aC6*~+%X}^%j=~0nxMk<3!t$d(dZ$aGmn;xa0vI8 zQTTp#z(jX7 z;kZYpZcH4~pY1gxu&-Y(sm(d=3uEIW!hvUSy|A!gu=a9_GBfGH3Vn9KBp`=(#{fFS z#l_)t-1ita)vasrP_PhgEFq3GdT<_qN{RXi9eiQH+%M@~Gl*t47YIj?bMNkdXxxgu zq?+wBM+p1Fe1!1PC#+pcjN%8?2SVIhk9-7!L){V5ky1NupqylRsNxh>_zhmgL_dsj z@fMnTWLme#O>7Wd-kt~)6x0ct5u?2KzySi6Fhb|*;9w>w5eo5J+PQ9a0+r47ej_+H zbcLofNU{~x;}CLuJw0r#wtg14YFL`o-MQ1tN~xZ1z@gmP zb4oaZHT?oBPm+Z;zImg6rHJOKFybj80l!v{$z5A+u`>m(hO+V>{(pCWMcT%c`$|em zH49HkKj|*#m&>7Nx_N!QOL+{oSI=;q;bMV~!{$t*C4Qc42!Lbl-1p0M6E6}|Pn4DAi`_3_{{B(L`)dT7k#j({dNlQIz`to&s4-y?AO z$`wWo%k8}(tos$5QGAK7z~I1@{=Y_KRcYsj^8x{*QljG&O~p zs6;#A#*f1dOn$b@0>4S};Un1GN0mF5vDw#{DV;yfUAb#)Hi#W-$8t-~3nCgH2(KypFLGJI!XBiv!`JqFN8iz?uEMO65@P zr_P!yPZG5%bfxS2d?`M5Z}_cC2Ne2wbe&t(Q$pR)e2PnA)6Tx@;|@*8E1X!cc=i0` zhdPF-&W%+v39)u}Y`cw@*P9x1>(c(QBkiYdeQ+)JW#1F_(iSUTbZ(lIcx%?B>EdS> zS8VQF&0}426vhRn5`vA{SliHKZH8a*WGMcX4A+Pz-OUK#W?=q<=9&!%$A)!UN|mFy->Dxe#Vm0$eA#J;(0`MVVd4;Jj= zggGkA9ct`NL2n9@B*=}&KiK^B+c#p)XTTVvgjMB(LPA6HIzHVwcl{@I#I4foE@#r= zKmF_YgGq{~Dw}?MQ>FKXChr$r7j{sA;UMkpP46(ktS}QsU~x4}7}BJ@9ri6~hbdg< zt`CYn))mSdOnO-ax7FA0OJjfA3@f1-MXRg5ZeIa`#jIGCt6OefzZc z-v$J(_-=VPIgOMrfjgYb?tMT~c5R<#i4q@oOXNlPkO8mx{0Y92;iN+Q2gR^o!B%ZaX_QlP_G|l$^D1L(80L4rV|mG1sA}GcnU1$)WLyfy_jc&xf6gE3)b=bcfvwto$woO z1oIa#Nx?C76z;@-&!}!D>xEc`4ac+6*Ijb;t~^@|g?9GrFK}9+9vbD2rR*>>>m(~> zqgF*_>}JR$lq8BKK?Q#8+OvX$z=@q8@+=3J72&jexS(v%$6+dE_V6HPzVO$7D74R# zf6cHFM$;uF1tEq92<{&G;;wo@>0S4+?_gk0Gd40(dJ0;D<9X+g#w3~?K`%SbIj!z$ z>_#D!o7+zPGJL=1^-b_VaZ9u~M!jZ95;68p=mfL{ooo;`d$idfwqwG_91SlMocap@iMC?nTyLm3#M-yRq%Q(P~7KFpJ=pLs>eJWzHJUZMU*C~jwfdipR;V) zzm=Zr*JM)e4^0Y8=0GW%UhXn^!Q;mK-6!sQY-xWHK~7-ow4%^Omx>Ez44pdd7@PR{ z%J%Y=;FeIY@%to8MgLarKj`2cxSVgHB4(sWyV%0Zfk(S<>M{_zm*f5Ar{Fr~P8GIv zX-aA;c&SmUg%fqwNWPe7_T@8Yyskg2_ApT%ZD26(n7xuofJ{jiUnKZ5%`~cK>R)62 z=I)`qk$2s7Q_SI@)6#O0?A2?XU08-=v)`4ur_`zxx`K?{!q0ESAZpfqd+7OQo z*0xs~sZ_}lMYxPP9VD~3$4P&Xl9Yr~S`M66TKb|b!0z-KVcHH&9QCnZ$@z_PW8=R$ zJ2~Z!>Cq$_f$zhLaRcRCPgHvLzZyj9OAU=v1vdfz!A6ywQs@}7U*OJB7VZ8nD??RG z{zD!{g1tPm+Ai&{mS#+5HFMF2dC57C|F#Xn7 zXlkc&a^|MbJzd!Z{fVxIaV}7pFgTH5MKoDbvi!Q}%zmaR@cd9AFjB6j;P%{s(Iv5W zUh`det-Yi)=)n_$zdbDIGG{(yuj|`Nm-19ecaR#ffD?|{aDalB9l~Z0dJSDkifuP# z-C6R2&(+0~Dx1H6Kh=5mmy}kN>VA3F=C+2g(6kW)cid1<@Z7Rx;>~j(tDL$T*Wgx4 z7Db`NQTiBAHu$Sw03$TPoA>V9m$l)ud!zg%Y0_1Ayr`@%(?KBAN!xW(C+e_j2w;R+ zDvFA4t$A-nR^=RONItAsVVE$yeLa`y-PS!>K*o?7&yJ)Rd)kDJ;xG=Y>{5|=}d)w$!jwh9d>OF*0%8q%x_D6|IkWOqV zbc_t!mD$8-f!_;2419^bwZH%9Pho(pJa)Vr2sDbB<;z2*n>}cd37dagU3K-P`rnW} zsHIdt|3Z(Gn``LR_sFg@8xebLfO$pAm$e{0v}>>jxd|J`jKl`r`Sp2S9-|wdhY8Ap z^iiWnFS%PWInG}D>5l``wfaU`8eVFcoCO78+_*hz30B9k$9L{nEtI@uQUV9K+3UR1 z)l=(*uVq+(UWyceJdu;Ietq_RkA<&#nVOm+S+ofq$VgokmC^D&=Vd=yPYJ?(IFANj z$}DdW4<}uN4f@CIdEnQ{uV{1-q|Po*cz@GMrK-#-=_IV`HvvUDyGoaSs5(Dn%ovB^ z`=@H~6!-1Q8RbPRL@4^&nSn_K%Y4N{3*fmL9+Jx+KR~McUIXwnlF_V`I(cRx@+^o@ zIttS?H-oRi#yWatsCy9H@}#?~+qJW|Ul1aZ%Af`%ekIE+=O$ zD4G&H5zZlz1yY~w=*BgMLK$eRS$1mn@Eh-(KdY_&#*?k|w7p|AX3Y7NJWCw~WKVnD z`$fkd?Ai6oghOTSpMEc4LJTl=w?1bM&(M~)qUwY%Q(U}f2jyDjh|1FLJ$kG+VlwwE zoX_o2AHMVDsO*?O**ak3#+xN2!l`89Ols=qA02bj6-0B3x$P@ z-}8o>(7$rhIWb!Q(e@hJwIpp9!EbVM9`qO9tyCs30yYxx@wLa!sxoJ+3iytqQNrjQ z0D`4sPgotFZ{>W$?Y#PsA@7v;=NzkJDuv~()0 z%eZ3zErFAqAZi_)2F|LxY$-z)F{^_ z`tig7*UP z0bPuyLO;?OUG(CN%kN@-@V!k^-6!LkRp1iv`OU5Z7m#h0Pnz2-T-UDEoBumz&z|7% zH%0F&zkJEEOFjPZG4|hjH-D}pl@XjDVBSI}1;f7d=JOAVw}!TWz==uU5A@ZqU64MP zkc1bimf)4EtgQ8fb!N&GE*~ks1}G{z-JF~-!JBzPTCw*_gB?%GZ#XGD_Z`c#7YJ$j z&-n@}TN)K3iqxL1u(6T2Bmu2ZLgLV~qjKdN#JtB1WC^f==f$(+W&Qm$hhoI1e%-_h znnmwv&1x)6my>EffMzhpAnjF|C-a!}4%8dHdHJ&F#TvlW;umX3v&qLMC`n&4I@s~T zcr@1{x#g=GZk+VF$M4(xS+jI$v1j(E@q<@Pnyxk0$SCgW#i!XT4^G#r^_a9pWKL#| znd+l=z6;V1G#`EP{_E+V{i?lksQSq{0p{@Qp^5(eJGE_Q#aZHL;^)!=!eMhsl-2S3 z?wJfb<~iNJ?{K=(h?0Ba#Ot?aKU~J(#{)JRG-(}Aj?>bzQjbBQa<*w6`Z`gS$Cr(p zQCdGc;hA02r&@GgsF_Waqd8)i7Ctz$*PtCx>dPugJX-6%)xLP)`m@IEJalfZ7UIRO zojWnOCFAAh>9f!?Q?+}jEa7|5plObIHg~prjYuuXUv&f2E9PThGHe9qTmL)PIam7c zWTJ1Ri@dPRMSXd4_IAS!qC?T8OFdVu+A>u3IHQ98Rc^Z^3txqJTs>@y+j+)!4V+JU zBNCMxV7$reXVAuLTe{|)l%L{b7|)I9f1v|BbKXC-DmrrA{Z8LnbrC~$!OX=^Y9UDC zUb~5lC$m|TFWUTk4jO8yjv(CW{R2_{wfX6fF>sKJzh7NF!T5vsw@ga|Dyo?wc5mOt z;?8)?URy3oMppRQ^|#N=U1@FI6>UBZc)qbeg2 zR>=R|?6rQpVpV#V9XBiU4S~TYm^8I2J6l6A7WBIs&PnQ0^z_pcdw50K~?b6a_@xF4G8&3>% z7d~HbSA`v68vSEu=WgBFouV)2jF3PMP(Eti z5XGuX>Q|oGh5Li+__itywy}12WPEt)()^N_ZEvFtul0RSu17DBe?EC~u;@kWk3hz? zzVUU^?jiaBQ(^mu?KWu<)n1A5@fydJ*@>$z*0y}}e-LKdTJmeYn#Q-?$=VZ>0LTJN zlrKe;_t8x6gCeTQOiuW~PkTol7*eute)`gjr~ORoex*zG7k9+=>llCzQXhHt+% zZcnypAN*CnKJm_L_+}5TeEJb69Wl9Pwt?vt1*M{V!7=RbD?iL-hu(jG5!|cb|N0Xb zp?~rBRd1o2@fUIzezitTvFh)p5`K{@Bh@VY`|oR^M0dac{2Rm?bEy&CyKWp65hvlik; "p != nil"; + "p != nil" -> "p != nil is true"; + "p != nil is true" -> "x = p.f"; + "p != nil" -> "p != nil is false"; + "p != nil is false" -> "return x"; + "x = p.f" -> "return x"; +} diff --git a/docs/language/learn-ql/go/cfg2.png b/docs/language/learn-ql/go/cfg2.png new file mode 100644 index 0000000000000000000000000000000000000000..617fe4fe4dc32fa26d5c3cb0423228070621c128 GIT binary patch literal 65430 zcmd3Ohd-9>|NbqdXp4kU$-1qSk<2_LBiwd&i)^7pgm#o9tBjDncac>JA!Lt4$;h6` z_B(EU>h=8-e)sqL>eKT)+}CxT=X)IQ<2cUCi==vLD-9D3fk4=*sBl7qK%f>N5GbB) zT8DpA>EI%c|DigseCh;YmHdB^Me+Uw!ajoHiQ`(%VIyC!8Pc_`tWL(Vvus!&aNuRz z4*HR;foEQxiRL5*?GfqMcknl?Z;Mucy{sXJQI&bgeW!z4r6FWEWJ4q3n zolzpwe{DeG+VK;5d#Z-#@B4~hs;w?PgC zfB&epNy+}-KgiyV{Qu)WeGZiP-%XL|>FMY$nwji)J$o1#sVh1C>Q~pcmwiz}}eHSTBy(-jS)PHs{Wrv#{VSG#4!_1`pJ~Jh}PWwQG)!j`@xh1kcsu zJor`er}?y;oZQ8Wy|~G{Cebfn60Zm;-n`-~hM%;tv6<8gKX!G?)~)n3C*|ek)z$sl zBErMNgM+z7#JTqBUQsx8sv?Nr;7vinYwPwb?PMK({hS@Q@NoJ6R#2OPnb~!+r|iLl z2M-wpjq@G)1{>r1O5$$byqTMui!aNNGAO$Ki;s`*!}6Cqlou{s*tKgHJ3Bii@3_a0A15a#$FF^YgLS{W zvQbe{srJw#5J*k|J%65()FLB;FaxHeO+DM zAC*{Dx_>)CjV-!V_d?3C{}XQ8?(3UhNxrF{K79%iw&)oe>WESFk5dVysnF5Up%2iJ zpP!%K&MNu9i~PyIu{awpaqay1^JCp5CTGsfDYXg-2@SSoUTDSDoJKnmHM!1>svt%6 z)*f!3FQW3(r_=eGgtyg<_%Jh9hp$V>9Q#^ut>=Rm;&m67>Ol^Uz~#GfadFt6%h#^i zH75mT2!Hf;_bp+$u?rxcV`((%HWPOkoyZ7$hi@m{znc1LRx4o^+*=6l>{W@Yq zLPEmI!b01;c1Qq!B@&0G`l=BUh0c>bSpLm4G*we_*mePZljw19v>p#Kg8 z5sC(@q;rN`)W@0{scU0l85Z4lH!~=OWuGCDE+YyM0&Yu_6}UBz;ndgikM_J9XCM#+ z%Z$lo{mK0+>3OJEHr>TWU6O=-A{WXZA=0QTM(8&N7@a%!9g%-+tkVTmDkmpLL!OC| z(Z$tuac&N~RPps|xKVe~W5oL1d-v|$xwC%b#_mFw?3s6?9l6Zdpl3oC_Oh_>a2MLWn~*SZe){jU#gQ?#lPp1o@S5{6&#=XD4olV%Bgni*X!dg|?-tK~! z*Nj)Ksj8x(rWU{Q^D}lpLsPT)9_nhiIMVw0k?H;#W=ZFXJJh>SJx~_-mCbM|rhk_* z-MMoos$9wHimSW(%ER&;^Ln{wJbgn$`p?@V?NQN7%N=+xwdTD`h%~iHYbiwjDW%!NIMFH|3P~xpv(vp?1YC za}(!K%b#*6C%kVycu*vR#F@7^t0Sx7D@ za9v$lzJ2SKce>Eev9Xoq-`y1z6{~m_tbJ=k!&45fqz70X)d*>+0|$Ca?`|G1`u!p^ zGqb}Jbt2_V=1cWxd4EooH#Zhv@$E;Ry8SH>6Eb*)SJv$fg)Y_4k-jzT7$jDeCXKH#q^R7#kZ$%lijKJ6x=9JLJTZKz zBX>B$V`U!MkB~@871&hBYGpM{&#Qx5=Ql2FYiQ88PLz>Z{bE;Q)0sCp5aID6G?Z6Y zjzAE8tg&}3kz{QGf`UXH`%kN>)uBEngb$&FC@3hLIdcYqVp@4Gq^6<4q4Ft*y}do^ z!VxjC;1}0dmgdne^j}${8XnK@q4?W{@r{&~^( z#aE)Y_IcmeFa7k%`rWM!2&X@by)@crnIsl0f)O_wTVk;<1li z9TGlQdZ)MdqD4t`^pF0UP%HvAR3Rw(L~J5TnXK&FRD;)?s$mJy(d<(6w6qNfxswlf z_x1Hv(r+htPDTF@u9J9s`}zO?K2}!`BfJ~j+1aD(q!;;)9ed-hsk?mICt;ps_08Opy!VOpQ0os5EG)0XkBt?kT+7BLX<_-k^~ z%hxwph?zhzJ@vorij1qQt`5cKC8$R?G&Fory>Vk1*?#iG3FqtAtDbG;mawrIMTapi zcFV_CG^_yCzQR>|EBzfdP!b|X{v{GOH8pitSC`DnTy#!0Y7iC|?FU8Ik9W_+bpT2S zWCreVaLk^EhsUmPvK;q#aSIheR_`wePY|yS6aUfIN6*SCFgi0mjl!uPuNvN~v?0JB z=((h16|G^kr{{pv?%lg^fox5JzoX;k}KllGn$0c0IHj}ZDSQSf70e35wY50V5jawNzh{Xcku{Z+>iZ~ z((q*@iHKbN9C;j&hJ2%*e|IQ%@^`lfnu|)T2DJ(cOL({YVk$b=RNT6xO;Jp( zukB1S2hfbz^+G!wY9b=`T)gpnz0%xA;N8DV86gfk;%c zc3+tvz~zF4wp&uiYPj@%^g}9Rb@UAkLZ3YYOg;bea})+&hRyG_yRi>zxgc)WRfv+u zIE_xX|8L>dZVlwsZAsB%7nQg=H1qvFTh+6TxhF1P&dAQ5##rMt-W85XIwT|{Fz_ns zJ8IYkKvBQ~R4Ru{e7i1O_z~g0ps1{@Y;I<1dSl|<#wmHMkm$b^N(1^-2##ACjE}f- z4OK>G48j$f_-_g$!X>{YX2^X?q$c8zk$gssTId^CtarC$gd0kpr59~GiVIdkYInZUaqA!Qlu;{r*tbp_T;}FOHYpq`uxZ#Yf1#A@(dU?s?o{)P6DMEz_tALmYh1fdJ%ANNq@9tUv-e90|pV{P3;Wo}`yJXyhp zQQN-aX^I%g3#O0!VLE7)U!G zvq%Jid=do_^U$}xrDY7mGO#mID7YLbE*=f^xAi6td5yROdYQ`=q0Ni1o$HkM?GUmXe{-QNXlquP;DL#B|FG@k?q zGtkoZjE{GNPmqu(z*DR)45!Pnq&@W~Bq$ay&l-RT#Fk5WtQeN>K@Zm;29{?+uNmggd&6MYHHT@O7zcOeeACat;zs2#15Xnd^y zpZq0_Nf%+_#H2;9qQB_#k} z6*V=sV^CtlBfmM_nx6O=q zcQ-eS?A!MZ*rX?Mym&F~-1~b#i{ik+pg2IQpvGl;tgc}0&jH#5-tQ|}%sBTxrn?uw zd9b~wWHY7`o>i6PTVmaAnv(8ll;BA&ZlNS3O#T63Sr%;>QTl2?JQo!;zS2jSoZ0-f z(8Uo=+##NjRMeB*1V8N25!$*!xr=(V0VG&HPosUVit)~YW2dU5QkQZXOF zGek{yjEufyN44E_!aB0FxY_yn`SaO7@`;I&5wEzoxWh(@q@t{Vo)dB^wm`6G-qO<2 z>|m2btS9J-T3Q;Wk;|Rn zc+q6^^z^iyTD-+To?xCUHaGeJE@pMAS}@im3MlZygPkB4Mw${Ett!sEwhhlooE^6~ zefpD?N&e9E>};{)z~jqq*akdpWhlDXZ6RJVb^kHaJf~PBnfP!2hu+?_z90#{r08Y07N|Bifq2GDs_Y7e7BxCf)EYgE=5A?6#{%M! zDe*lSeydPaEvr*QU)E^OlBFr-Q>RYlYE}meuJ#3+Ak)whnVFbySB;Qd@Qhp8 zqz!E@+S-m`e&IFm&SOdk{^-e^8NjXj{4Wv8K_h{vwjKfj-q8W1(Ageni6}GwR}1dfvN=oK(huJA3RK z<5Waw+mN6wtc|<1R2f5I@3BYk6=sg} zJ|rUYHP1de=MwIBaBz_3ZVwQO_rr&%3p87{1n?M{`q%n0@ag9y1hhXP(_bAX-!Lje z*rKORlTQZOfUN%zmuCkCh3U_vo2zbZJp$sZNy!A?2wHLs`5qk|4HXI(1sE%awm|ds z)=7Qu0t*IgQ4>Ia6Jld+Cg4KZH$apV*B+Zkx|urbJ%-{5R)fjNMd zw(mVkqDZVB5_#G?FaQ|p0(iP@+csq9R%X$WuLZx$eVC`GriAzK@$ghuRGd0?vp=@9 zw6yESZzBVPFW0(n=)Mte^rq(p2{DbLa_|0qHVG%|ssJ8@LoQWx&`CqX&W>Cwa-Sj7 zQx=VJCME9VDG5Us#1UR`YD;mS;GPqvDV4yKT9U6`zfO-llm+g#8~OCX%)wy_fXNLd zoxJ*hO31jf&02kh;YsUK4D+*=+JRl0t{WN|DSH6DDmPu1`|rQ%h?w0^(>z0hf;cbG z5@c(1)W-z@@I8qNiCV1EZq8T^jCPj(?!}8^qK4$BITGSxO2l>DPphL7z z#8?`67oa^MI<~VMn?W8V+>imQ$iR1I0_p0#jLHTG3TEdg5?0wniI<1R0?aU(Lse2z z+7KsryH%NX_ij-PWP`_aC)YlxNrqV$E3pg4>BdEB((}E6O6Fy#4?ZjsvnXJe%Vk^| z30g^Wb91;4o327}PR_WwSeZ05^MJfC9()wB>uu0d{tbHCM2&-kUi2 zOSGdm5D^rv8#mq;wdvqHlksh7e%g{g03Z-kaf)%#n-5H%KxP#$3?I8r>TUBqHZq&RHC;nVnzh}N=CnUz*0{<1rTS+bgcvgwZOD3 zg)h8AfkV8edt-hPcJ1<4+N?PbkrsE$HCp-cqdBq|u_2%vV|fwx+`##ex0ux;x8PBM z_&UM_(;8HW><<;O3c@IODdI-ZlP9F55p)M=FZv7g!1Yj}cCxajOLC=U>DASlz)4Z5=eOgU1arFs|h*b4_T!ynOp!R3+8HaNdL4D`nx0s zZScwMz%jY+pg?KHogPGXBRc9LWX3^^y`ZhOL+dffwQN?Nh7i%#-i|zQLJ*p+5~UY@ zMsJs%d;9h4GRg>)5i-aEqv7wbS>nEosv>6LGXb=G;rw3W{TDBc`?|GKD%(3cI5{}H zmcdL0vc(ox7=o2GQgO zI(-y?TtlM)U%UA29pzwRUv)4UQ$U(-j8|hjbk?(=pg<$B5M==&iI&C1@;o$D0&*vK zQ1e-y)GM5ZUfDeuX%>Eur@xb+>8}kpc)?-|F`16$Zhrne>J-{LyA*I5gR*ips*Z?d zlfqAzA3kC$D~opU5@gaXAOWBhBCb>xN};IHWdGFA(BM4%YyzQC>{RG*ee@uh#T%BE zNtc(Jbxo+dITE*{>Y(nUekFc#h@N{^kdR>h?d{D5O|*+4sG)%WcVwC|cZNZmh3Ix# zMWtk}XS4ko5VuwC1<14jdveVvM&P2aRa|lRv6g#1vD}qj)Ve7uY?ss%vWK zeYbAiYI=GdA))<$DZmUK@A9|r-zPCvD5!ycH%Gbw;T{qbV~_y4#|Of-5R{#zCAUl& zBGD3YM%IR?vb7ua>8|(^z;-Z&|4%d8V(MIT)@Pt&0FS`lA6jOV90%e zXDrtr$`V_TJ?gd6-fYX}B#Z>e2?lz43oG5BV;q?0b%*m25zq@h3}wZ}_F>N&8XGa! z#d2JNvYgdj*3t2X@4bLYvE+sFEqCRF5HDn%`)E0od<-t27-(I03mDGLezDV?`kh+- zv9fX}+c9O|(=t(n`;jcIGuS zr<<5`q_qF)@Mce~XdU@=mVz*~Mpb$0pRf_(!nGmb;znt#sFE0un4QMF7Qmw!6OQn? zZKiCGI7cf$9cyfEhL5EATOjZKoI5;6F+%}MO#0oX+WIu8=g!wA;}`&ECNEw0^nep@ zwCf(e@a|}9D@2*YLRME-!v>=2GF?Oi`Y87W@||Iog-`nQsZ;SI*LZ$N8z=|y?KIn` z^6XGlz&Uhe|Dc}p7cTrKC)Y$X6u3`JOpKpjzkBpASs^kXB zHPfYUuj~ta`XClo340VTm;nNhjsT=Rjiu9dvuUQFq|!1Y)Pr5y#wwXW;-2~StEjM0 ziE;4z_o(!A!SFC9R#xNr*gOb&_$U?gM3T6J1Wg3K3TMhgpwQ6Q*T?gu8x?Rmr5P82 zO!Wg~2oyR)A3vLa|8T9sJ*GicS2Ev4e}9btw)E@qcl`&KVq%ZpmD|b0l+>;f79D*7 z!& zEe6J+h5V;L(LO}FuM8?rIB16{V7*HO@1vmn{ zrO>Y%NBHlI_9Xp~w@*Kj+M_`t?bChg-3X^kra2uetF&cP0=y)25xPL#j^kZYpj4H% zpV3C^-?R~7#&4=`>BU{9z1Lz?>AK-b)xg82_4Rp65)u-s1j|r4VU%d7t4jy8$8g7> zY>yElt@mKyAUZ~ASPAOTyVBD0z>2B*xwH&h3LW~Ykl_7w5rS6bNyET54Q2qAy-FH4 z%HR>$y_=>2do8%^yqiEs_gUM^30epsNI{>rfU%8nJ4@a2m`uErw@NS1G-48c$n42- z^l~I%BBUXdI9+Co^XD}N2a~*kD{)iQ6+k|gjU3g$V$nl<=aQbJuf+IiHdtKTVQ$H! zqlZ=u!HfAvg)bXK)V!{A6#Aq4plCLfY8{T%7#tV~4iA@t{0%yeNJj&n9YI_RVt;Qo z3~K;jn4%1epK0r&7dWTD_*CS2jq$yfW`o8xAWp04Qx_4Ge;>s1p|s*_`ua^#bdxVP z5Y>I!Iy%TyIvW0NR{#~^^B*3d>`g=bwQEZ7d(@t^ZP3!+uIN__<`dH`n)3KTvaWU6 z+SbTc4>lL=uOVQBIZ5#6xKc-u{K@Rxlp@sQ!*h?Tdce09Fe8xnU#L&H?Tc=0X? znYnMbA7k=3!^V90LFP8-qxFHd1Dwg~ z;ruNSd(tbL$%;qeosM!tL zRDIMM;2#~1d-OTjLiob^`jWRn*#DqskNIh0c2>Z?jU1;bXM`@*?zMk;ZqVEAhyHDu z<4?oG`M(Gt8dOr+Kz%KcP~#N3{X*g!orcP-uH)6AE_#P z1MCFQVKUg)pkb(`)r48Gnk~`$=;d#o8RDIoslneV?TwC)NBcTvQ3nDBqb!MWKItBM z;%<8SqMsvV6WmBU`(Dg|t)SaDwk`Jht3hbLb0JWvZ+u+Ph%N6#gI@Kz!TVg6&wx?A zDi8!(q1D?6o@Re&9^)Pu>l$DajyFrUgGKh+w~3cq699;Fh;Kn?2rp_!9_8mx<t} z4S1*pB(_@ku|P-&FJ8FAW(V)$HYQidg5AtT?UcC~9O8ZxzE4(w4U-I~|Dln3W`@?N4$IO>P65P;+ zN-%AD#lzOa2o?m$*W!|%(^#U5q@-j_4cJ7aRq%4({{8!*T#Bq5m%OMos}TmG`t|GI zP^Vx-zBby?H$0sD?nZx?%K*#d9Co4kx`PI&KuEy4X@<`O138>9xZp1y#^ip+XWoHrEYNfWA?o+Q~wisXEBjueP14#OFNz9lf3^7wHrhD}$5GB^X}pZWGb zJ!iC80u8dFnKcg%EjTCn`V{02Hft;j0`lRfgrQgfKFm8dLUgHIj#lOA9p-`D&7 zJB(=pW3<097yiOza%)Vx9$!=?otzHAr1?5cr2Nm}VW>Q>F*__`c7Ol=eT1aTc}vTo z-rlA^VYNGAOy?zZmkNXi?iEBkU_XX&U!}dAwi3Foh9&Ms`d?TjoKha0gJ8dYO|bvQ zfsH@NS_g{x>3CPVi43cf4m;xShB}XG6lqhzj8|+P&=bt(1_l^T6|AK_Ryv!Sa+ZSm zjgB9`iTT|t9?_}fkqWynA_-+qVAgH2i~;NgO!K_UcR~MRs<;8w5VYV@(#@M$jcAz- z4a7-7cmni&Wa7%i!h_yr}04p9aT-P>V)wJacjZt@KK;_`QtjUVu6#V*XjSV;3W1 zJMtV)806fJSb&`21_Ted1F4$-g4wrRuh^sTW!M$Z_X9MdR563x$Nrm^9}*T`YAspe z5QWtehF|sP6rLfMVE@6VG}F(o9t+o31NDsK4Ptf{wag4>_=6;k91 z4jRrQDCiT&T2MIfSDRlfE3MKh4Dt^RHR$=+)TEXBLZjb~zQlS^v&LI3f#_b)I-R75 zRsz(?Zac1J2uR~BiEcl2aaV#3Q_h8oZ5BsFMPC8*$W`j;Z=efUt}{T0#ngZ-BI_PD zpHTbAW6IKN?KfXu%7Pz58d-*e^9SB%!qiP7ea4MCIAXFWa>dSq=8A+14;$3b+S;9c z$u~CEl<^2F4K7 zO*#ILFCn)B!r(FBblL$b7OCr3O7BpYPGZu4f)+PfFy5ZcB_Uy89TyvmN}=}SS|SOG zpT=?6hyW-;x;wT)0G6o#qBA!q`fN_rA5U3>i7KKFD-5C z_H=AupcNHuifga5TVBpQ(7GU~TvTjSUogp!l7Vr+d$;&z|!W5{i_?JCTFbj<|~ zGM0DB)XeM^EFmaLpvl4LLU^ix|F{iz3IfL>Reb`=4gx)?#%KE1FaDJy+AuEu;p_|Y z@*vbyfUrOtAkzFIW{Uv)>9FJmYJjfYNfitWagsoqMc zbRbZH3t{itbax|$MC7P0=@|kcxsNPj5q}ypVFXGR=Go7f5>{$SBr1Q?iQ<&wC!9UaF&9u^RNa7<|1zix~KDh(>W^c2gD zhXVw{KjX}lGGk(FY_3@i6MWXz?NIEpHQ+a)VZm_--sGP@&GD}hzxH2WG1Ma@va(;lZGrxBGO2H;9jJb}itY_ZOp!D={ zAVJ=NVoUnX-F_0E3PVXr z`zi6VC&#kc5?vE4KD1dMFRz_CUUb}aG!R%Y8u_qFy*V%&4rb0E-@(+`*%_M%VG+mr z9x)yPN0KthjB(f&kPx^M-AeTEVGJdcD57zvpZ9$Gw(qgU=g4=MNYJNR;?*Lu=+>d# zK_JV)#USef)fW~@^78URD}nC_Un+l$E#a^an~ZUa2Lfl~`t=`aDM{RP#K0u{M$at- zR|o3M=Z`e66KG&v0K*m|1@(H^V_oB~W^iu(9P5Y9>y}i9L4_zLpWyy?3O$090Nz}5e4x}WI>Yvg7Ie<#q z+VsqGrEMvdiX6jF&4&Tq=LOlYPg!*&?IzZ|RI90}AvYv`6 z$eAc5wTw{}DW}U#2j>sU)Y`Gn7uZ9q#yB605`CN-2u(Eq!!wx*JMrbuF`R>Cf;7t^ zyo;8W3ZnMHj0HT7F1IPPKcGyKrIsK+JO~bI;)C;I_3IP9*hs?r#SRg%{<8|+#V6J}HVf{e=)IO7v*a6Cf#23$pMu$#L{({b%$=8ZgszKVYYO}0C^`-+@ zO08jJLnGN;t-OaoFb;(_g&Zq@sP(g+J!$|Zf7n5{Z`)=TtJI{5sg?DJ*&__tu2ALJ zqqcEn;jA9!v|qopx#^T*4<9?G&sPnxd zRK>xcKe?@hBeO8RTj2j2j*<21;-#r-4P$t&zhs%B1(A>7Xs;c1HH49pyPAAp5VS{Z zp(r~$S!qHDGKAo`pPXK8V`Dao4FI zg@qmj{kUezgesi+0l$Jj@quV`WMvpN9hZS605S|OO!kOPBC+b@N7PJwKTHP=4>z%2 zy?PZc(AZ_b0JJoCjZji>JOgescr)-PC|O{Aaxvb66p^;tq9qvXrX`Lc1eF~ngCPW* z9^dE&LV`e8csR-}Pii>^EcD7ja3fe#KM^L9BAV`>1AxTQFjPT|hsJ~Ff^iq{3FGq_ z)_D3V2k@mhf2;&Q3r{*893PwmEWqZAirONbvHA7U_n}wwdMFZlr;#?;d&ITrQaYCH z`*BUkh7$qCiCShjlT1&~6R7k(s)$=g#-uIAaMY_vE^5aMPB350%*>nBMj#ttoJFkz zPAI#t3bCr;5@|$RkCNn_EQ#C)LWA=LA2R-iYU<{;gk8RC0wYV6%Z=QHPF@@jO-8}I zUEjlw69Ly*^8xS%h@ckjH(3!}e`E-QM=8X-x zE7gMFl$X|U2Ki7|RuaA!%ZsW2^$>yuJ~+7xtC9J+bLuMvgwFvQLCot2k@}8KPUKL> z(C{IUh=bX#zlN?tttERbLboQEWA7oAgXBrh0SI{xIL~Y8>8T)WSPi zorq=}2vKr52bKV^3e|vJ7+1cN6_!!Ax2}=G1qK%>=ZSsbJ@G;C@bD-)j~(0_9~T!? ze7855ShvfS2X}zgogCD}&BLvX5BauX^Nc)>13HvGotvN_8QujfeSpnHcX|96{<&J< zjh>z!w7i7&Q**$D~m~017xjB;tx$#IhH@v{{oSXG-U-KoiA)C=)l|!9$Bv zf}81&=BjPi-mDa>!MztI?V=A9h-Fn(Rh;i9&%O>0fLrQ7GDe1m5Y?VP*n+OO)#2(@ zSYeg`NPr4CXQ0Glri0JBv%A}*%UZTfQAGu#&I|~ym~gP_(B+#(R`aoMh+d$l*8r+W zSRAR1;$uKJ#weWIcc$qeCnp{Rp2+t!cja_-U&E~=r$R0YfL2T0I}-Nc<{vMo1z8T!bXKa%BeN z2gW`F(`4K9q>PNUR}-*G0?6mICE_I7$VeyXDezw)X*=G(kA|n`^b5*;fgvGG^z`H> zK!ldZJtxyzn3ZCLE)f|I8>>B8U&UsX$*kp!xMcX2K(m-wWor^`j* zPzV?oIXwZmzj24LeC3f^M7-PpADEn=V8X(PwksIW_vXrADbwKFVMSHd-K?@G2L?+^ z*HW(&VoBT}dGJA-OKBm$8DNqzVB%0WNGy05gP!Du?Y8<=NQL7Q@UfF$YykEflK~(O zLyJ3q3HjjHXb&_7b2Br}ls!21&SPtihKM@!(2kPVC`9K>F-kkTprBep81!MOKm}#x zMlA=JdLh;1S~Qk}?t(fE<{GmkQ~qI3%l#rEztHU9YstGh97OU^Qc-E1Gs?-$y(^Lx z`{flQdi%3yKL-aI|MD){2HYd}@85@^wtRe@mIyFA!0E2XWRokaBzf?B!X)Efm@(`t z7d7$w_x4Sjo``KH?MA&t5_|#9&&h@<6tLFjbL36KM1l{w%VC&|9sY>-6OfNL!L#0`TKqb+nYT7eJ=$-+z1|IV1I}Rk|5oKhX+y4PE>y=m&DZGKn-;TN9@6k`)XO zMF)1Wv6-w?!+JpWq(c+HEP+o;i_Xy*Z zwyoh>3#&uO~}!4nwXV#0o#Jg z2)|FqJ*QI21oR)g)P%&|cMO{fd-Qjq04#WRw&Q#{wMamZk|W%mI5!IDf++7owa_-P zwX)(pJ%0s=$&;lA6e$@Ec zxUY3}c4$aF`Vz9ajyMVi!2@1r1qpQaOb8xHCH)>~dZ1eFW_1EbvM?~{&bD^6w^N(u zBc5?W@ovQVCTlz~Rt$>o0FX@j^1hSK1db(L-L*QsPtr3q^EjkY zGBqY@L*!HDFI-HlVb;W{1e(ocGEt0^Q@%}kT%=29MP_zPBF$@LGoACMqTj_t7K?Qn zF=-ptU!}-A`(H+ix7E8_Z5wzGqzLq^o4sYErFCMEsPg3TfwRXy1SVaH_5WQ_h&M=3 zpIxWONjgdEccs01*3YFf?uEhB;mKtC`j=-$O| z_k_k(WMv7Ao()Y+Cp;=2Pf;WQdc#SkyHtme?t;k*;OAWLKvQ!w+6PXiTHDy*bd9I$ z4HnT2iAUGnl*MROU0eJ34{*Zq?D6r{zWw00Q6gX@7e0Jg&dj!|vQlWjR!b9JByi@; zgHLp|b#;O~JW&q&Iq+a`NI`0OUtWIig4uh*+ZLRvad2?J3o9Cd*&7=(l@phr;#Dxk z#lKVxR?XBbC4;TjK3aBPxC$KgO!K2dhlTIIK`cvF&qbC)sd_hdwVcKQ~8yWsg;> z0KU6$9i=DSjvR>YOHNLruQUw}m!MJMK+p$X;;|u|=MfaF`}k2dNe@j(L*^_mCnpZN zc*gYc@$;XXqB+Ze`iuR5l^?@^aG)K>j!kIg7%9NSeIzsiYJz3mV?WJ3FgP~mzPcin zRo;dEj)4L%pipjnD2R6@pnh6eEh45vLqbZEf|{6{6Z3H1T=K?(Fm_Ww;BiPZ3&+8O zoGKxAQasGgo!bvH`JH|3P=O54X|mFc!G{?ceHGlk6JQJl0kPoZbdO;-fs@@&0TT%t z1wOdTrn=8?P#h_RHhSv=v(Y}~NxYpZGVn8AQj{nO{_HIrHLzAfT)^Jmv3q&;5W0;C zQt)FPI}cBy{LKZEgz!AN#ZAH`6DpnV{%})UdHnAlqBs_@e1GWV4ITx@uBLKw=?g3Og$Tyh6 zhyxBgHr>GhAIbY1kC2$0?At$RJJa0Qh{G)!Gcu?MO$U{BK&&L2`M{`1-+1HaxAW2Q ztv14OJxt8Z7huGWjt1S~F1~1>qvHh5`Qw302*Zg}(pxa+;~hU`uufrgUO@@mT69EE za2$R<@_SV9nh}IX|A|d+e`;xJ`agU2AfPvv(^PfejuR(OVs`Y)t-@V@_YJTZ8XopL zFsP7v59UA1$9Ufm6xdS@4x}A>p5W9K=F;<@D>tlPpYdG$iU3PrfC^%gaE39ahrq=n zC}>jXY=8VX#Ve>Ou9a3Cd|H&DIZk(Hg@nxco8d^C#JhmqS5nn8Oeci)7TmexLt zd?2L|&h6BjH#0Lb?tl0R&fTP>q{G6h1gaAU{D5a~cdmwqgedhbcOz$h%0VG8L)JZd zyekqv_n9IA!#4trQ5XZ=`GlJk4#rqNiOUIWlU)tMo zT66=AKqJG`AZ1J$3JQA`;#d#(nS-_mSK8lCHQh^yWI*PwO)}9qKKd@m>%b8l{Kj;I zpa(61()H~3Jqi4bvGEFkDK3p+_UThv%M~7o4%g6a?Cph)9J&1^fUs77b}=x-Pw|Qr zkyNAb7K}~Xw#l>J)!Iw&Y?dW%yZj871!7yjVT0dRFKF=_H*OS!pF>`TFq{Ai1IL;$ zB^c!Yp?xpD?+a*+QL-th(X=itE)c}FRJj*OgE zR3v+lF#VE;(&}XwXXi(c9$~h75?a#S)bwn}!MRuzE?{x;XyP`17;FcQ#5V0UJ$sfs z!1VN-x3%4Nfy7;_Rt8y;9P@Z!Od5Ny53-1eh~VHhEOtoaGp`@jFDx$NMN@0Y{wWy@ zop1=iTZSNv*VNz)gA2Ri6Dm*jV=%eQwfP~; zFsRt7I6k4K7T-^$$jJB{Q|&Pc3G%6Nn90PCuWPwzV-x=Txz{ziRo{@14v;)}9~7Dh z=%LAN;5N~tj%wQ5Pl6(XHCwr56}9O;z&;aG4=p_*0hhyEG1gTSIzna3%K8E$6~;w6 zT7@&s&CLq>0+=3-9PwZH#hI6%4+pGYP8j}t{CL}zV9GahfOY^?tTOI<+1R=vip5OIf~`?dQX+D5?<+94Mf>RZIeQ1<82nA}E9T+wFbvjb7bE+2 zV6F`a41CVWDho#oKi+E>%<&&K5YPg?l(M{A`h>L*K@@|qlZ1O3vf$5f5m-j{?u|pS zaGAO|H~T&g?F=o+?+yBC?0@4Rokk!_;rKFEj)sQjFqhn04NYsrhSW2Jb6kgZP@Az3U5(x1wxXq9Gx$3eQtUcOr=3p48LOkZZBK zc<~Cr7{+TXXTi_49)n_mSj5$vd>6b?toQ8MXCaP+LCL#!kLIWvo)=sJS_|^`o@(7? zM@JlpKOG_c6`N67ddq>H@~r?)vp*3^K;<;44cbLV7ltDan3w$h8xz8<-``9mAN~VH z3Ib0QFZ#;3#I#*=6@Y{>Oat(~ zXNilhLL-Ne=}nHkq$Eps_hRq}T{j7M^u8XuSaFNE|fWpBtjUlKIs`x|P^d-zSOiL<4VnbbP-HBkmNk)uUG~4toQ=larF5 z@<`y=5DJ{91T48&@*5B%u#_3xLcGI6L)XzT@kl76r=3DsmCl@LYiw-%^2HS%i__b- z6N2!nL&v_VK#Z^3W`!PLq>v5Tnw^<>Gq?Mwv4;oX_wFp&Z$Je1+fe4+FdCr)V6?au zC?|h=YRVyKL5!}23}cuS%5K(wgTxQ-U1~zYzTsd$zjlNKJXss2=?T$5d^q67b?jJ3 zO2os5)u2HS9U`Ht1iw9c`s!7Yr$Mlk;~2o`(9p{%S!3fa$gPMl&{mjV?v+!wm7)WV zcbBlCTs(aW306(b?&T_nh-M?1c4V7!f;#V0DP=MnNu7*<1^=f|ON^}|Oi z_b29oF-3ZJm3Vk$%oM=KkHZ>JTnLWe+7QfSJ{(HR3eXqDB{4^PdvPciU4`xM-ce9J zewU!FsR@5XF6gE$lfHZX6rc)Uwzt1YeL1=vFF|_}W{7tx><~+_z*{fYK2Rfq5R_z; zgP<)*F|H<|agL6TeiTJ#C8SVk*q;qR8Q%gxvt>(+p{bIhB3`m#1K3BBpg1IlJ|inD z3u(E}(>F2E0v-jR6M>udg}?&+0|U_yKdE#6xF3m$bxH>0B&qSd)_y+)L`txr30OE= z(8On9y!OIVkjra`h%yN7=R4O0X{f93M1%qafqns)+43qhD{G2O1M?fiMMuB?H1W*0 zNYj299=Y-E?RdLjWhLX~jR3naazG@?Y*Ohyy9XUwVC@ZrWw_dwy!ZGvy!@yC`}cR? z{d(I7Zi`>>Tj^DfpDHuq~ijh%0d_X51PYvJ~bI#*4F_2eNHJI$`O& zyr?y5G)|q`806Nkg~kWCRdQvp0ceft%PBxV$cBh~Y!j)8?kxU0nQld@;xOQYurSCf z@LNDKD@}Y@nQ28#gM|?=2rvodGQgMC>jRiZv}SZ0YSd~O$+!EkvUraN2=W^ccs)H{ z!vuz7J?(k+?44N~j~W0hqnM!j8|mqZw@Cx4|IyDZEiF%P*_y#xO{0i>D6R6o9q4PYcfiYn?j)&N6G^y^>>y{Tw>Q*s>?`YK zHX)%*FtDI)Yd?Q}Qu$qoX)(6vO+f(=`wluf;ctW-TSlwRcZ0pe|nP5&Z0# z!u$>(102G{tLI8xC@*?OA-V9~thBUKc&}mADWDW|h+ZhToSfxLZEttr?J$^6{c;R( z62~+8@@*V#Inm&Nml6Q(h6$-4k*eC;#Sa`P#VZrX&+JLYjE=7d(eDD1$5VoQug8v| zqSU^SV%DMGkh1`c0>Kx?en=ivU*Jo_fSHRB*{hl06|Q0b@pK;8Pq^s(rqs2ywQ*tt zPF3(5LNcPB50PD{=4c0nd3n#K)KM+4Yv9G+m2C8+ocaB`qP(1H{rZchrd#uFM@B}X zJBNr^p$G3%Stox$P*Cvj;VD>`F&r{q-Uw)iq;qv~c^A*S5q1`I*-N##PrL&_AZ>Tb zCH$Qt-f{=yH8x=0aWrccb+ zszomG7$mHb3h=jpPQr`^QlYw9;#}!^fMLu{@$nU(k21noDS?3)a8@6rG+@icix(#z zKUhHwlgBMgN(exTYoF`u$!AA#oEZ;5u22I!{QO0LWym!QSCZeh0ZO6%0I`HUnc1J| z1seXHbR0;N@y>j-%!k(=5yaqIf^Ne&F)9SFDK7f<3uQ(+#0)eQ>?2wzw!wX{Ar=e# zjfLkMH>L^j&KYCDMo_X&{oJNlDR6X;h&J73X``-tRfbAMa=Hckiv|x$oca z8rE9Zy7WQZ30JUc;jpY^_@pG&Rl8T|j2Z<~q_D_@O33mDNZ#T$X=*rgQoGr>Bm9|x zeg>i!M~)o>Tyaa^n0WYbEolb!a;x9ofI1r8frAEh8<{vB*zEc9ybBlle73%-v)a$^ z&Fj~AjG_g3`~LmCuOG}1{$PuY@C=fp{@W2Bfps{GL9-DUr@#NWXXEeMptWEo$hm(r zNec}5_N`k*##8eHfeUFvsB0xQ{Nx%7W}1f&i+{GZ+S+w-(V`_w1fC*4Ocm^u0K&}0 zps8YF9mUmvXQ}7%=Y78(g|xG|k->!;c}38qCr>C_ODR0AU!PcJwQcLxUL%}-VN4Uh zcdyPkeVz53g+Y)JC^LXEc1BS+K?susLrSH2r{*ipsQq zbYm+K6$oi**s$gKRuIInEP~*Cu$r{uM;anx{$-G2$j!PV)GwSCu>M64B^y2Yi4l==aZD+~+Go$tOTU%Pfwr`hhzHsXF zX<|=-)0jxHHK^3rKxE_lCH6cH!h**Hcv5IQwZUJo6Xj)-mS~I(hVP!HArHnWggT33 zg1#fa%z2iQ$UPx3ktsb!Z_i(C`?e=G7SAIa9^l=gxgY z`f0GVS9e9Zx#4b%^pdIcjy?c<;8k(Hxi^K&@Z-jJbd_<%k;sOwX8 zZWvjXkkR{6P$!v(j~^$ZM}POu@P(?%1m-b7Ac=@;J4-j*ee?*2f?kS>1`)=cV(fOq z@DghY2hC$+U=Y+M%$zkVGCaIs%!CBeE`vZ_o9FWv2=-7-NBBiJXWb|*or9%VfZtlG z%v<}7&of~6S#fE8cqeUyVs!Msu@ubQOb|xZKv^X!n<1{v^{4TrpV@PA;fxuLAVx^N zh7X@1rjrB`!2uM6C}hogHT4(+d{v12)sG*)ly-6S8b_U$@3o7rTBv;T)7Kql<+Hx%84-nWw(C0>I3@>wv_@nwoQ@`I7A3{BCv5- zI?TFnMa0SF>Rr6}&$4B@qxADV;KHa~B6!~6;eFF16d_|D;)}`op-jFhBb%NHp$w2g zWyvYmA8IotD z)t{k1tgz9J^f-|cIO{(xz^_~44`xuzbD^M9%j)!*oo6x+lj<2X_w!wkbbWRqzkT|u zRcC=S>hi&uEHL3+vP6^f_PqjMBr=XzyAx zvU`9S<};<75KMQPP7N6_0E`brImjnuuF8lv?lsjbcjB#fv#kOh|0F^s>_cREgdD^}7h)%mj{FTh#Wjuv1Q# zjQ}q{uN6D-;nOGLbyq2=#)gKZ)fYx1Hvr6eHD(&VR6P#ke5*A&kW|+4^QYhH)g#q3 z<}%yHJLe6NI<@KYdp6j@F9iTQuAJ3+=HO!(G)86l# z->UcXMd_g&1iS?1UtWKX+Ob}Z`j^s!QSlCY@~ak5Dy&;)X!LnU%418Zj$6R&0t3a2 zzAb+{dIxp7KR3O*geT920Tjn=aaZ%1_ors#A(p=)v ze5=J!%SnG`#KD?uZEf=hYU?bUIeYd>{GFlf-G4)W@TXGCQG}Qb4;0gpp$alW&;Znk z`l&?4$J?8COl>G&6Lt$0?D!>k`HmPoxVhzv=C@)30eJ193uA~@@BKHresL)@v$rf$ z8{SnYhff63P86D{$8eUx!PcX7JQQ-5fdmk%#kcn@UAgj3ZPAm7sW3U9nKS@+AG(h` zpteST^k@#=J6=3jIlhDZkW8Hri#gWf+)G})vJjrcW6NQ zSC;m*e)G4wBcR#r5e1)Ocv@ZEl`<4w$X%A+7~Ls`_cp2a@YZi?-HUX9oczQY1l0@4sl9Dgv6>m)NSs6+r z4yUre)s6NK5V`yb8azX~hlT>{Y134mJx!q85a0w!NyXd=cjf-ay*X=?pS#95x&6F( z#$RujI2dx;xLJR}ehIE9y_@h89Sv2Y%fB%%eq`6bX=HNS^$qTp)Kz5;#;s4M&Vc2NwurW!Ld%Dj?Rx>jBc5ZcYmFCn7l zqxftHjesU`bxo`(uyN16ean`O+4eF%{KJP2#!TVE;Z-YtMMr97VR4OtTp(<(OO$gk z@O-=I%k7W^1V44eMYElq_13mD9mRhgiCSqZuq0ty;^;3?=d}a~;x-U`X)8T8{Qzx; zS6H~E-k33zuj*5FzF~f;vT}z1(CoKewm7vrGiDCdIm16rtKh+d??SHAaVfC=drXC{ zP2|hWzA(#0jb*yAIXyRb{oDP-9{N^@L~0b2Py#yJvYK`L`G8jvrYon-Cgq*7=0%Q@P(FTgRKEXirtKMy#5O!s+Ji2-}=8@uVz z{rkREOOh%%zBpCTsg+6yOc23HXrtvqy&(_x1r((B?iogM&*7Vk2`3n5et9S1s z_RnEkr&QFG{7!tE(3w0e6VBoL$uD>KbTTQ)3$ZHmuQ6w`y8PD?i@sW_$Ivlh>p+~@ z2M&L0xfz5E;32N6nORx)A3j{N|E}H|zD0Cg+!tDSt^i?l+55vNox!Ax3=MB_TB;Pf zi=4Oe*ufhPExka2@jm1tO*C>L&;?Q>IEAxdA2>)uBSK@^zkt4xul3Zao*HisO+;@6 z$Y{CdgC=Gl^!?7xNm#!g=^zRy<>O(H2jE%SiVg}v5~y(K6bJW)Nkw>v-ANpCCNoq1 zF(Df*(o9nS>*5X*Pthz=!{Hm+;jz}BL2Fu?>Hu6}zF$}aNe!8Ga`3QWMQbvxpL&TD zUm??ALdIzGFN5mba=yGVedLFe3vCwu%iye9N%YdYrC<2^8K6B~b)Vka4+ND0DC3Q% z(F>z+`|b&UbYr#Jf4qBuH%EkdJz<1|E52}A;e>`SU#9QX5fm2iAjo#6PnXqQb)Q)( zfnRM^K6m_hc*2oTi^GQw)$kv+H@}nxtx-`?nOH29UsCzt0rQYa+i!Ng>@lzp7wa#N z?qJSxSjRuQKq%7^bvvvgM{I`YsT8S*gch zM3KvYRAyoUQH`|OP01i&gW)VCJ8%A*$0*Zg&+h%Gu(;UoMZTDTjdvIK@}|wA(&Swp zGPO{@`)8PO<*Oe*JCs*cyd;1sDNWVyvjSZ;ah5y|wV$RU}P&YLV4R>&A^Uvmc!gsp= zFRTVg5$}Lvm}udL0+B{^d|e=0YiL}^jQqfigS6NV?Ow^i3(<(X&!gcL?b*2#dTd*3 zAy4qH?vr5&E_NYQoO2c|8~O>oVY6**&3^BQrDGN-qY~Bv967H8gm^q#GTG zGgC!5<3+jaF8ywjwY3s)12KzEL$`@RbPWFf?dj<{JY9qiUX0^Wf?X0Hpkt`Oqvuh3 z@l-uiGc$dl%7B9_3Pb_-AgbToO0>$}_>fo!yJhISSMkL${vD`eP}{0$Vq$@~9PkJg zu1EyV*kYl+f9$69oF9IwHnTW}@*@I9^-O+n=bx*(jsIQNv7`8SfaeQ``i=ix+fim0 zj>^}%#`>P5z5WBhN)QG1o=i;@7z(T)|1xS1qy|&U@c8C}Gq)c(bVvtbjQtr&0|qNB7IW@Il>_>55qdNm%|{ay#?%wC5(YN~vx3v}vEvN=xQ|8> zbesmbA-s#|5^4YR+;gm>>GN1?@ZhyjupI6h)<#9oyc#n5)mC;X+1vNHka!Q;$I2?i zT0?jE{hF4RF9dOe>IH5cB^;79fUy5Uiy{N{7;9kgTL}92DJxqK>eq1n49AXShdSfB zE6^I-Z0?#ao(MLWRv@g8q4Is6=l}ff-H{Pzu`a`aq5Gsf9@oefHm)MaUQI(}7q~~J z7!Q4CX>LAX=+K)Kyc&PF{49?dC^WL|CrqeiGZHm@pE&`d^b?fDK)*j*T4EH2BfkZs zD3Fsj*X_`q2T1{b-yR-GZH`1N&XVu5 zM07Ks6iUPaa+VlILZe{hnGs|8 zOLol=cxheO-z5BKXzXoKI8FTF`SAl}&)es3VZHfZB0qn@#pbW8jyeU8hb613Qv4lx z{M4zgc~iyA)IM}e`jeR!&x&O-Has-6nc2f&?|OjMho|OQeebaWr4(c%K)!DmInkP# zj*dB;HS&;WYIt}VRUyRFUL~1PcHaD9$UusBx4o>XK^YO0W#Vi@M?%|;)^+>_=0F(m z;Ny5lbV-ka@j{!2K3(Q9BXNNB!@%Ay9TpE*eTl{#lGgovJrpd(ja;!SnA0#4%fuDo z3=|BQ_xi^kfkm9O5~LZujC=9VlW@+fYYIBKCwePrl_F07^bvyNjb-E!D#l(D%x78r zvtmWcPr(Hz`p?cbjx1da3aHRfNdf*1nTp0C@iYS|uR*xwB)OL*KsmSgmHLVb(9|0#PM1d-}8grOX{%P7IT-&EeCrGnep0+aU*>|pG=remN z$sJR?JG6qF-UOuVv*7=Qj?!a52&kqgYJ4lR_@w2gc}1B(E2Bq(ZuqWVO;OkwDJ`1T zK(hf&H1f?{%54tP{a=I8bFT99iwX<7x&}PtS?=l^`S}4ZV&eIyIUum2rJr&^55`jM zReZ8{@$@c1S_aWsRyH{ci5duDuU?bHhfZ6#aNMX-6{V%@O%T0f&h?=F^0^x~UP?>T zx{@I_t5=U6C}W;Ico6(uQd(M=AZ0$zU}7hcbnTlrj7TLjh-7#p-Zn;Fm~ac|9&P!8zA)@N-&Squ z1)lKiS+fpLIa&Ge;Y-Cgl8s-!ME%v^m4y32)zQd4WYERVuE1DNWPsz#nZ0XHZP_AD zMdRo9gLA01;>XYtBaq>&`|(LRTOec!^3G|i`-_~FISnWqfV=%0Ydbwc*xgDrN4lu< z#>rhGrIzMy^6n6JE}%Z?>-2P+=z z$f@&)f+8g)*i4=3712dBOCQpmv`1mUyG<6-QDNarN^F5#A&UC6zrBQ!#xaF>bmSEB&+8cE6;KJ$Cqnd`yU$TUv^dKM?_%4F?Pe8om%ThcykV+{h6l#xZ9Cz|)*9A&LWlAN9qDy9hqW zM^*AH4FEs`Yt+;qpO-iqcM{Du_{q*8R zz^y{0@C47Rn~VZ>gl^vsDVUR+ixN@Il)KLA6N+ZieDie)M;i~1x8M#Ll^@X@60puB zB?Y)Sh|LAQ>Ziog&&>GdE<7NeWm1xo9`vq^5@&bF+&z!FjUJKzg|VM9MLP4|V_*>oL!Q!x z_3P6sZGo`0rtBwAB~{qNcmPN9bWpeP7s8;lhDLNdXZ! zbwNFO9)pdlCLcz#R;^x5#b&vIoC3-uC?H3Tvldl#8#Bg_@D&(%m74+i7jv8N!b1f4 zXKX>|>wB3=Md!|+Z^y)fyl%MxvViUvoPn5li+6{as0HbzW^Qlwo5pBEw7|49%Nr(#CQ4^EA=F>fVzfbdh-{nB6q2#+>RKx|-{gnIl zk9Z99&?WWL`?qh+RJx^)zz84qjC-A&lA>-Z^oJPyKqH(Cl#%RMAWZGyxcadgT|D2b zF}$;A&DJM-l9Q6sSAUrGHMka>`p1tS3v+$LJhNwk+L4}OHwe6#&52Eav9}`^#&7~? zaMzFRA>1P2XWy36N-ZrA1toMiM1O_}Q24K1xUhd~IkUUq;?hBJBAFm0R*M&>1O;)M z`$r!jq7!&26?BI8vubyE0vtgODu2BaN7S$H>`My8vIh+wtjHy1at@<{WbR%5pWt`V z_UNXa%xsL%mj#|xP*P&5Gsw+alzxV3kQ*f>tUeQ8uxcbbzd}OZuu4$K&8b&hQlHwJ zBfyw+iPDl`lLFa)$CI%qrTQx{?ue|J0@>WwRxW!9r+^}~1{u*14N=v8(kE;b(odv# z(FaHs=%aa!^TETr&rV*Y4d4F{x6LXMNhjEZ&ZJ&mBKUPWB+!w|Cr`?}gZpnID8glj ztaKJxL55(`K0c8kLA$r$g3rK6HL?6pY^yIasiYFpHg(SsdhQCM0@y%5i8;8JcPYHd^~E=)RzNA`7tL?dZND|vy^WOWnOKGMul9E18Q2j507bhWh9BCbo*%BB7y%aDT=a%CM7l zr75*9U%Jd-2>8#>c4mIYe{jp_Mg;|k-qyAm!dl0N=8X|U!Xt8=@#{&wO3KQkbaerW z-fb9`d$g7jfeiOj`TE=#tTaG64nJ(6i|E_8FQ-}HJMBzP<>mPU8_@ib(29)p@*Q{= zq#=t$N@$XMbV!E)Cw?o@L9l$zvK!b3J{HAO(v&Oj-oKx4!TH}$DDwRZI7B|G^;wGE z5&sY>#YOJ!Nu%AkMhE@d)_rOA*ArIbLe|=5k6(G6&a+${$je zjKF;f%Re4Za>(}W|A0{uyBOkOPAssW=uZygu4ms2}Q zNrlmvlfOMxgu0*KD184}hqeoxJ$>DzwnF7%=0cjB2QIv`jVCkw=ql`N2 zvQVcnpyDEP*7Q^S@4-e|6+3VglR@oK6H=i)YKP^62VO_@N+AeBRjxuQ!nrRnO%v&a z?%i8ObwRa@@+Rg00rMw_pOJ5<)1DXfZv#v$H*LDiUCCX)J11u?D8%vO??c@>1gr+5 zRP5V#GnMDkrba=}4joq8Pr+GFJ`BM^Q*)zR))MM?GRRirSTI4LC$ud`Y#<}Ja`_hS zkv!+S&z?p4_2gdtgG0#IVYYwbdM`F-?ieO+)s=JRKKF4>`}o(n!1{N650E7wu@BkM zE95>b!xDg&^76KAof6&){dvQS!0p?m7fhQL;sEC$_(R@(jm`&2s@2+QBFBXU81&^} zA<-!me>?!yfrZsDAsFTb=u>O$-MxF_hlg4skqvzAlAC*>Gb6qWAO>i>@a+Ho1e~P; zMI4Jw1d7~wU@hn#Kfm+f93V|x0lJB;e!jlgTj2u>QyZwqDJ?52qvUGb z(M4whRTDuECMISOLr?SP?+Xg*aAk&fEbRol8kwG&=jb>;*O!emVxL1DCs04)g$cid z$c)y2p8L*?8&hrtYRF@0s55ZjHn(278^68Z^=E^O>^-Ih0HNi(cfUGD``_mvQereU zXwM!H)R5AL`$ZsGT=C<6BeHghaj| zWkf$0vw#jDm+o*v9Lf%3mn~nu3A~DTJ;`7@d9~=+ zoMKiEKqzk4C*Efq{qkQ}5@oNUAtZPl5>|yF=qp%eAktY#;KN~x$}=VZV*mXa@Q{Ob;siWZm>xg~nCBr6Ini27Fxaf9oxAMFi4*^Tn_Eva z_$9sv*w*}u7aARwCO3H<;di$a0b@**WM%INqV6L{06gLBAcp7`Hu9n=;TxNpzW?~~ z84L*^b8X1f{uKA-sp$XDvm!#~`C8Fa=9rS!0d6tCVp&pnxA)wZ9y1X^PtiCToM15* ze=M}O#9j{lUOD;5P>Wia?()1VWGU2qFZ%uI9)+)C)*Fa@g75)rs3yoAA}iRvs=m<- z)H1BDTq+d;6NN-Z2nPEEFQ7DgEBVeZM1ZnD1s2(~oa3lm%Qo%Xzn{O3@>IB8p7Ng- z;2`n{P{ehOBO`)?uM-c;7t=GK8svDkGAVp{)thdQzBV;&De`$2*)(0kSiw_|w!By$ zk@(~bcK{@*5YS-KbO3+EEA$-;YL{{1Ib%do4UroEz7LVej}Tb3%N9xt1FBFr6Ol+f z&~n<>2zYX*r+@C{(kAI?csOWMDpb?jsoXAWz0y-0bb$O-xN`QDZ(* zTw$&_YQR{DKXSft<1(L;k5l@Ibv8hpnoE3f=?A#2=k>i)&wS@xSOOnrFQJtB0T8m`t`w__5z;<4ZA- zoMcCe5xUQ;7D_dGUfG|Xg;R^bl>0tC0MadBz4el!B?5?Jq!_*_sGH=lnkrDij~{PU zmF#t;IH;=DrWEWmDOd>{>-32e(w_%QasVk309BW(K<>b_7q2zg1*$$Lin3sMOnP4e zF*p{F7r#w^^fYh}=AX|TI&^hkzLy3ix}svJK5Bm}$Nv9&>iKt}VE<$|^n|pQUJ)Vo zl=?4}#hu3iHzcM^G>$AnNqF}o4HeYP3q_fWP;XmNN~ESPnL1VG%A{L#7)Krpn-x$GdCLR` z@mDL|P4C^imt#@zY4DrgJ{lBW1gxyE-^TxY^lTg1~RPs*3y9_+P@ zrj#;DKf`~Jvm*T={0()$VLI=+I{MDrzxw)ev#U%p;MC^^_bl&ScQS{0wiohJ7lFp; zM;5Efhrtk7Bm%^fJ`Jw_Z7X@mGSeZH8Cxn(A#nh9MmBmSqsPZWoM-()S<-n50Uv`H zt3&~CZ@6u~>W?}a7QjQ;Vn;eIyr};|2Js0M_k={kS<36dvuDrtH3r^DPTtxUGZJRx zL-|K=B_`LDf@%~&y&2|Z80Zw&l_oE~Wfsf&bQ9WPbXYQ>P%+%}k!?!t;5VgW0hlAG z(>-RbYiU~a%k_W3G58&D#s2;KOY}iD`O;VT)aYqB47JLgoZTRcEzi?m1^-xc*iZqX z_#AutApPFM=ITY95TE7)l|?D+K93oavR$~sWTkJrpWd?I`)EcD=%(CJyY*Y=X5Xdc4I#oPAzW_~mqRKXr`l;NcE;2M_d3OfI1g z>pmN7;tbN;L}=NFoGxZAsaL6=yN4B~9h8}48uZgv|d_am(sd|}cp=DKMV@2;0mC^pI%qKU9=&x1m-5Mlh32LF+s zzJ5xZWBqM_Q4;;v2pP?)ae|8h)3>~SPYro3Q`1cpUHvx)BP+|-%gca=oognuiQ%l9`;C84JVY26p7PqLELt#hUUmdE zb#+_YZ{s!V<#%~ZDMAbK5%%1pqPjZ%!3VK!3{P&~J!+7gB;DANHb+8@CtGCpI?bqg z%L+-e_CauwVv9oKlQ2}yW6#Ng1S_#yi1vl~ zJCqrMQ7h1BO3G_O0TA4s^832_3dIkkiizm<%n`l)j)bb_(_cR^-m<60$dTQjGWIbtWS1lZd+sCH)x3zTs>{S)Z7Rg%&7b(&rkr{|beZMccPj1c71a40K+~e8;28n!q zv)C1$U^uaVm#$rv>tD`5HZ@{I)OfXz)n_|jj*g0w4LV(5z}W>_I-s{yzBTsnnPrre zM49aVSn>LI^~S(rE`wD(qk6Txh^_VVU)QZa$-cOiRsFRYv0H2PUk4?!J&LF~B&752 zNr|*reimN^IVU)#$FgPJ49vRs>}g?WayTu`@I@NhjStLNya??QXvVh3sE7!q1~$YS zfNF?E9gcWUmBs@JG7U#`s{b|ZZL^V%Yf{+cle>*vlu;m99DIQ!#=~@9_V`>#k0ZT# zAF1D5PYz`ps;Ae}w3H9o z=c}GKvNW_AM1PC#bD2qjhr#Bn>+e{oHSjK7^>m1+uY%u5L{7&b%DrXjOE=QyWM@CP zcFjF>k8l1(Il*WMVI=i}*d0T?xj&ZpRn09%_`H_d@!ucYI+D=a&vO7O1$afdyE1p0 za(qMjc=>w!>lm*cHkrA0tpQ>!fWThz^0D#pfS$;|`tvZA7y z3l`W^)MRzN=dwNi)8q3|DQOlCKaBydCuFZart2k*BKB5CfygWgO}fT;5ufxt_hPS8?9 zKGWHv@j`_{a|Dp?ta)2rvLo0PVy}9smoHz2to`lZNA}duv&Qu{6PTC!f1h~K!-spm zY`#N_^92YG5V`X1UA2BmOn6{jfG0Vl>a2dAWp8iZUsqp$kntU0V#$seRY+Cul@d4Z zX{IX2$^<<}6TPmnw!@`$uibY4_N-)$O6do)AAu<@ZrkolO?mh6vaZb^DF!U)1F!2`p4m8_D6|G8BETuC>I<&Kvu@YrB5^bT7lI zUvnS)Qna9Ph}%C0+(7WSJ}iFmF;Bj9@xTKpHu8Hsc=+(nKEt^BeR(oL4}MoGSNDDR z|2^W;QmNmj93ZDlg@;C!t-b-sNLO-KOc3#*VxoE^FryK7jRN)13pAs$vsSQ}Ov-bY zPQ?acQ@-iaz8Y%%PO7Z;*Y^AG(dL`3E?5Q(5PYR4h`XNhltNX4p=|coB>?j~yfaS& zAGtoCj(nraXAKo%iHUqduL(z<(b1PIzClmC(`U>Br69WMq60fpN>f2(s@x1yWSmh+ zd|$WeS9ABzp;fXk?YsxGE{!}U7FP^|MQQX_FaufAHYDGp%F?wv)eE{-rH1LvfT9%t z?msIwDPN;5{Q8R7FJ-U(!sFvr#qD2rFL_djXI-~0P>j-XU+0uL;YvsAq8XUrk8X7b zETl4Oh!jj&|NJzMu20@`Rd-VTcAsbqkUO6zChJ|*kDx&HV9Br#~b zeX@InT^}EdME?B`XzoLc-?-#;>!4!X#1YIN!*gPuF6s*VWmNQ(jlGU$iV<>MpS#c` z-tT{-7D-C_DhpCEJxR<*#Pf*i2uw(QS!JtR`yO}?2#)~`ib4=&sy3ox=K;g7Ndm4F z>UW-B?V&?oP_-C|=O)*JL}ruMq}`#*rTb8v>g4o{%9d&xwHCu-+c*7W{0k=Ph)r48 zE2V(UV_#vnn9tF|5a_}e+HX+35+eqv-}Q@yB4Gb=pcxCdX4u*$eJ+g;YN}*tOzq+n z>A=g4JIqu!w*6X{z6zhr1H&`Cb!aesQW>pmLvGT&Gqud+NuWS0CP=nt@-(8ko`BY+Sq@~RAsxut|M|Q9& z3|RSoYo&ANa2P)BZm`3AB#ybm@QrHGcU=f-0Ps}w-Shbs<@m!H$RYp{0LS;6tc&#) zLt}u65QX_A|MtzOz&JJ$7kh0IK3JmO(b|$V*9VQOQeKm(TIaba-w2$O*Fn=J%opt6 z52cG*yoLD=-_BI5ux3gF+~qXhZ6ha*xu$ss#xMP!ZSs;^xs?n$R*X4Lt3*SLOW@UB zS#I7tS9NBDN#aS|$rWZZXI47DQPMH&lHT0hOvDM%4_Q0%e|2ZCM%qktYgq_8wz=s< zn8iCDo*xus=i*YsR1MuQLn_s|*6s+RORu}o-Fe8y)dc@AQdJyTt|ya|I?XYh^OI}y z;ltEIFHL>>f^|Vb@UjRL%@WBRfRk80Lf4zbSc8yusVf;B#~`q->$E!9M=SYV@G#k7 zzcpX&DS7>?wyjG=_wTY>{6jtDOaR>890sLrUGN!b+4zUG4kd$>?0zww`C$ ze`ry`r1T$myS)ZtDhX!PvD|)ab4v?AUWO@H$N;IRrN`DOdszN9t7u5y{C?}wbhjch z5J9KXWb!p4O8IiY#)RR8y{4gg>fJkJTH8esCUC01#3ChT#6KPuWB# zZXPObrzx3vZ5_STw=dg0tc$+=_;KX1-YJ)oi8#?-#$*uL+#$iCK<|{l{-bEF(V*O} zJA#%JU3Ji&W(Qmf(4?gWoa;Dk{hn??B<*bIP3z}h20YIQW;7^2Abs1z(#ie*SAY$b z{P{saLcTjU?Cp2XLg@p|4mm;hr2<_W$0ZC>y_YW8HQRkyw&TDMVdXoS`jH739-e@a zjp+u2HP0S%(qksOzii&8HzYEs-E3k%#(=r>Tog2hQB5XFfoA0o9~SE`ZQYP6(WE9~ zp5|2gsG1i}6aITFCuM(r*!4gm)j(m5f<~5{y0ccak=lvt7WS*>^tJm`m9Rl+-_q!q z7?4heCv@)B<1O{&ΝKnzv=oWLT)G*E~(y`(q~Axw(BG@6&M+e_Bw`@B6}XVL2$U z4DDnjOm_<`&!y8?DsFl3k_UA@Bjf52`B~<(`UHG3l+{q^EPS-20%3#kpP%pIX$F&t z_vYu(Ja|WRl##I0tQt9(lu}=RZsB1yg^&duWG=2y3Q0SCx|_6g;ddwpc7dq^WSxn2 z6yU1tNxK*H>sx($-_C~o*T=~s9xGQyx#`pkM(j89js*k+plBg{!NI{R+^fEKui%%p zW3M@}L7zs=ahav0s8au2OPGKA`;$Jl{*2%t0hrpR~ET41+xAm=+iFq}w#} zz{#H8*(hE)vI(cJ4WD(=k%1Qree)p(206%%gil4R(zp6aT%}f}{VHEh1y8VDKQVYn zy?xN};GvNWn?8Fctf3)#K`$~IiPGxr5h8<>f#sh#%i zuuvC7UCVJO;6nfRdCj`kCv^$4IDYcvwGq8$;YSd%g270ihWV=BJEg@@c^-P4)osVU z=x`(i=I0^u44XQrqt7P2Ff#|&4YDxdCj%Ey?_mq3#kGLDUr=<$@^3&`xV47sKMp8~ z5?bAW)$cBc7|I+iTMcT}TVEmd^yx@99cLXx&UnXYXe3jF!;}KvpOQ(Us(8H*M1pCi z%`Ta}GMAO0%=>DZmz?|x8GPuq@$D|Ix1z=eoB>dD&f8C{Qz>@-?>mW>;Vj}-+(<$M zNwh@2lJuCDh}hmhqQl?}A0bluA4ermq%_x_W?|8B!`T+3084Y_KY(aGg`tq@H~|*| zhS~Us*&ZuNG;}5n+ap&aSCD;r`^JqUZTU!+d^a#2@-;$gHd90IKYzALgmV)9jQ>@- zY9KIdaoD-agTReIwS3UVJ`-G|JK=*xgS!998%_BzCLIocHWVwSe=t8UbPBTu{`XC? zlW4nF6u#{dcsQ$yxb0zDNca1$cemztv-cgZCOZf>7ax-IhMpis&a>gyVkYB%A;#vzq9zj$}KMm;YE0)%y=NiTE2W3;Uj@G94m!r$q zQ@&A4$;PDAKrO9xG|E}4z%;3qJPW;ob(S5n>3Pk(Fo&HhiGzuEj{lDdSo zPh7+LwyOi)yn43bnax0rH=FMK^sF+Iy9O_aKbFr=Ux-$fPs15kQr!> zzBe_w>L}hjIM$!UFagV4l6f(V0Z19)Is^y1?S=!p+%b2vj`(JPg z_$nc*GS!sfN=t7`{lsB*fm)czCzNdz4|GP+LIopidR-S@`s?6VEB@~61mLZoRrUy> zZ{_ZMZx?ny%++GzM7t=#`inYm@&0F*9QJt~7^SHhqOEi69{)Dfu*1TIpWnREbQ+Wa zTFOqaIIlaz#cgp1&EzbY_~T-h6eF_W%q(kdW>OaSp4ce9+3;T>R+KN5QY-gr{u1rOF58 z<*IctwHuyI_Fpkiu3tZx#7SfMKbtZCf4k#fJkV@11t(p;gZ-PW(;Yb(~)x*dknkkH34#QmFB_M{t$^X0_BUEU_*)d|Yu<{7rD6 zihk4kU0r+@A=EnTKxm3s_X548pZK&)8q(MHRxZ*N+L~V{fg7uv)@qHh!*|hoI$U^<*{{E}sGGjupDV}+(~40! z)OZ=_N&H(6l@Bc_TCg>*=6E37U(5j-x{XaIM_g&f5@d4D8`?wOO#jDQhYlI?4?s0E zHXAGFoL{lOSq$u?z@}!$73&@C^LpP0hsn{pR1{k>r?$t7+Owt>Qx;; zKUJhg;dZ#=>M_$nafZyU@DhiO8S?|_Qp+9xHuGVN{<#cGVi$$T=-SIh_tlH)gpHJg zRy@1lRU`f_tYOc>&F`u*j(A!@hyKR88%7ETE)1zT&;aD_##_Zh{dXTvON&{XytcF= z>gn!*n{QDA4sw;tv!A--#)+nujWw|)0&MZWXFZ?2Z--SdI+<)AF=Hl+d&0k3kE$$O zeAe=HjntO4UtZggVAuk&7KDt75{VFO8%p5Y38QZ?Z~>@%Yq7BNPk!Z{b4<^zu#3Bw z{KuPrcFp4o%d(H2EK>pcSAQrdF7VKAp4x4u&1Ay>cFtl-_)^e}rgGzwJRvF=a3JpcK>D^Eo3fVz=4>g=8`$8c(*pM@^c_dzjI;V_Al*L~8|l-QP0U61f+bG;o( z0|mp)WJ!V5C@C@Ud1cL3dSH~TQE0rkSyztl7P1Ozn^9w^b#{*3Iymm&t;LXV+uxM3 z^v9d{rV^!j;^BCe9ya&vWABGG$(>GOj=pNk5Itjs*-izu<3j$^0yqsfF$Ilk>=iM2 z1fh|~&CQb@k%WBOhN1}*nv$zn_g~UO_QFC^WZURRrYOT==_WpUUx5byRX=vCT(DvVms84NFel_y0#=u2W_74t&e3yFT z0p32(D`s)3V4%u?T-uDzGK%F}hLnGBlQxvvlC$nhO377ful~k+eQ*_jaLs>K*xPlV{~lsyGb9fH2yOXvr6)kg?0yBi)r7^oc=3YpIo;_ELSlJMITi`o&YU@L^G58D`ECQd zl`TFiq|06Fj-!TZg+b{Ng0$>|-j8M_B@s6oPF>TM-~zSwZ1wv(77vS2n@F=D}**Kt1z?e~*b`hC3lTAyr{b)pwn%s}X`5 zE3yzpaKN)yJk`E5LMtGLyju%UddqZsVU5>?`E*=OskF(JuY4{nYuMBK@1u5zL~zH8 zC@F?EMklyC=lZd(xW_X^a}n7z1P_g2%f>6n2cTmp8cn=wEfB(Kox#)aEJY0rA>6{_ zM~^T^xfMUE7_;m!d%@He**%wsAvPK=`nhh@0!W&GUha>C6<~!^Gh65Qg+pyVb#=JU z>C0X7aqhx})AgC|I_FXt+-rX7z_c9bA_Q;D7-fQ=+$SWRbM_Ri&g4|15{!*n?dyx7 zIc>|ku9H@?N^v0t4C}@Z{k~HLJP6`7?>O@{3z*;S`!Yr?3@m9^G)oeYIz9H!0zY>M zpQf<@KiZ&`(5BzHefxBF_HNJH zI7gwS9=2Ts#!!`EzIMuVhvhRh;ZV^S45~CCnWH{i8eugH2u^`nyKTVIGj0)5?S{mz zGjZZ}6LN6JZ@7c(g4(T2OQojHw?JV8R~(hy{Y=$Sf1hW`EQs=GHS=Sy(Y)fwkKD0iU?K%P&lF|ru#0o0?Y%pWznL)l154Xpx#=hFkBxO*x$=4D6tQDj zRFJHNLtmX~$N(;+{JnniCARQSd=IG4Y5HiIAcui2-|jg6jgLLk0soa#^TsSYbez#h zf*D!_Jx#lK!x&#-ljy$P72P{tt?{yGTIF7WS)8B2AIZN+G?4v^1o~HQxU7))zSdXA zJ&P7SGKe{~ee253D+70@)?%VZ1MUdwqCX=>_R-Lq^`~ScUUJ~L;zxPcrvL)DDSMZp z_T8o}cQRM_I9b5EB|?o$T^OV*7~e({>n~77J~I!m|mA=utgO! zP{H!3X=Ge!L}a9jj43(YTDpl&*>~j2Z@AmC( z7c2gf0>_TRHLa{l4_vka=^Q)e^saX(UyO`8vhQfN1@C(=n8h(#@XzV$;|}u?yOTx0 za!XRsedV>cLC;nv1c)5AH`Fq-yMtH2C`1J>+nk`s2$R75;u78zLal}0lu3HLgErGsdBIVzRS%{85m_vzWwmmYMM)7hD6290}# zEzN|;S=T!zY11Vba3YQy;t#oO|KMW>8QHW+&0<%JG+M&$jetZ$5e@~DYCgS+dZmhNy$q8dX zNS?+XoUYH_CmtZ!~HRd_0+p0St^ns$r-$af4`q zF3$*@k8=#Id&08etWBk{IW+P>FOm!E6XZS#1{C0n@4`DLEiIVmBj0hPdr36qdtJylvAK^QgoqMLs($^_&6k1xy2VQd80kopi4vyV_C3LO_Ii7~0=chTC#WNu+ zyeBn1Jzun*_lsrNaRLQ6e9x4X4o&96QhTIrXaR}FQ{AvDBi1&HUR&H-4f57p_7_-K zUQWPAaHmmsl~1vz-Evqmij+4#7jD_yg|-*I5pbr%9f}oJ*;kw-8cUNrWY{!H{p)ZC z6)zN{dffIKstQ(e*JQ{2N@ttG@e9xx1d{V@nWD);qy*(XoPds${Cs$%itS#$cUL8Y zbcA%Cnbr09d&9u3KN2e+RlI>|9xl4DQyW0HCbi1*I~%?GDJk8o^TAj|h@D;J%^ax# z8U1J6u=;*^c@Fy=h~IB_gbxRikssnjsAjh}ei|i9=XVPkz*)UfhYyt7u)jRbu@j7g z5vFE2Z7p(zJCQtdaKPwI58c4KaSMZJuRQDD-bVh()>RaFJYqTkjKp#@_A*!$Yn}K# z);%sL|F9V-k9IgNuE!2Fv19QNNVpMYW$7J% z!^V30x0TJUBv= zktGjS5+oNl(gMUbuY#kbZ%(}SSkFJb&z3Yx09}OKCB`Xaf4Alo=V|K z6z7ZUP3)8;LH-Ys=@Ywir^Po0Re-^zAIEB`L>2c~XlA+WY5Au!e#uG%Ww;iFQ&ZhjmJCQ}Wmkv+` zPjPi58KoUyYy5&7FR=?rup-gvP1v5!5KsvKIm5@(f1+&7ahhu zp7vw{b3a}85(<*E11MOYT;9+-vA1^O-&kB@p}gxfW4AjiR&?1~?qd{Vq1=zdl4<}m?3uT7&7;6 zeRNqc74jau%nh=4&yAxawLQd^QFutK=5E7z#8e~^PYFddJp4s%w$7hA$>TJzAt9Pm zl-og#UZvmX+w+myqFt+) zDWOo7db1QT7haqSWobkg_tUw#b6tyWK+Aw|(a;#~nDS}k@GH@$L70zi`pa(gALV*2 zRH$kd12Qri(N^vtJ<&ZkcB^B)yIHP^L+?F?!~KyVpZ+0^xWr@rQWvrl$N z-uSv$UO_D_A|(~#8HYQ-9>_bQ&P&)Dsz27(jlT)5i2+mK^=PwdrW%h@Zdlwx= z{$N3@y<)s5`Z`P3Fq9lHzp|W3DLx4CoW`n(YCl9S7oJBb3GutizrXKKkEBu==dnLm8Xf&zf3v+3!ol81Tc&@`OM-edFe z?&Wjl=k4}mA0mj^F_ph|psYc$JpHn42GO#jUB8fE;+228)kRnqZN= zTtm{8qL8$GWQdCG+>K+$85lGJDHZHz_I4bLC;$={%n%!#M`H*sN4lP!Q-PZrE%Qh{ zz2qU{Iz~5o3gX6%GkKbMFK9KHoi3O!QM$QtH`HHDEGlvG14_Owg%SGPJY- z4H7Yao$Rn;;p9Or#G9;R_n&Fy7w$En$i7>PZ>+Qx#Ush#aXh=QD%EQVGi>xw@486s zoDaeQ=3zNmhWY0oln>+>y-uBy?z2rjkG-;hb2YdB3W@A6VLW}ztnU7U2fY*&CY{_6 zA0q%~YN_6(b-wD-?@AW)R%Ub&7X_?gYS^q_pu@iTyLRr}n~+fU?)A7ZKvf*!GuZ?} zV;9z0Y3xS9-mXB}nc9)>I^8p+L-|%3Q(A~cOcWHn)8+yKUv^d0F%uIj86&(nM@L6y zzz^O@T`wV{=*0}f$wY}o*WY|eof_}+`evWwAy=L2`3^YKbI!DDxMS!*dTpLgi9sVO z7oH#dSSPsN;D2<(LKaX18#`4+X$hGW2JF z9X$z&LTlHp({lC|y@Myhr5`3`_j{KN zN1}XDy^h`#AD<>R^jfY7qhK=yHln?H7v9CJ&n4cb;8E${e#I+w|NaFG_Ta$zmVcyl zZr?PM8HAcwdV}YDwR1gun`3J{yn{$@yO;I~4ww*P#;AxyeeOMYkP;rPrl2_lxP(VG zB7QU0m)$QE&)tlsSMbN?{J&mdwE!gqun@bSX5>_qlz7m{EZp>M*HpKTwv*_;$&}Ao zp|aFnmq_)cV*0p|iZYfGN0NlEER6P#6qrtl$|LwK@jE$tgPZgEyl?~A{(5W7 z^PTJ~Go`ZtxKSRv(SSD{&IUO)3kmiF+l=Q7eLys#n2qugE0>@N5%#X%J#4AI!H*4* z?|D7|>b{*M%I8yEJ1nO7WZ{U~{3DLp$Nt<;l&@smI=#W7fcIcUqWg+=-nui8;-hlx z(Zf9DIgDq|{tUc6Bo)tF_53@Ywb<0m0SJ8}03{sSIrHY7H!>5=L{Y4>sB9DRYUA2f1t&XdO1yVGl0BQ4cFlhOw znya&W7?VXQLv%z%jMxjjH_6fR)7=jYA=1vkxSG#)7KLm6=^*wTI52$vNb_LFp}PTh zuI28b*1UBpu!AUR0$7k}bg;v|uiPVMVN1R~h9F}?`slblH|o~IwXa{#91N4ROESBJ zU3K30t#USh%kQYLfG6Mi!LN}82Ey|8Ktp_z*$|H(bW5u1kj zjJNEFUuv0J`v-87p)SsFr7ll0;!vWVpM?)W>qU_$p$-y{(x7+s*F^}90ZkL3!xzj5 zOlYaPtOzd-%+zP3YsUqFVkPt7Qu%0>D{i^zD1vc3&2S4r{K-EWoJc9gT+ZMAKBlr# z*J5~Tk2w^?AutnS$=+%2*oODeX0ev$Ny+(!q@dM>S)eR~jp z0>>@&KbWkhU2 z(srtx1*8a*d0_GHB)gb7F%dy3RBsbI#+?GxZ4o2{U1ZD@8rPcC4D_XmWKEpmrUMVL zvSqqx`hD*U^MUagV;3q2Rddp7Kwm-9L>qeH`8-z2P&8PEXX=dyis!%ICu~O{UGB?MHg%L(=6Y578IRff{S2QbFf!F;+A({wAk& zW%d7Q?@YtF-rIKn*Pzm*qB)ukiD*ECijqv3lc7R`2AYMCMioM6Mk&&aiV~|L(V#&i zrI1i5QlzjyKlQBVdG_8f_KSV&SNnI|$6D)-{=;{;hVweF^GfbGzEPx>{oxygvYata zFbipX-}O5^Y}g;1VEO8F2jB2cBDVl&r-`cZrLf7-0LvR&0x=EEjdK`Fg?IAnw^+9ImN3 zH@@Wc>t<@Vl}N~sofC9?yby-4Jk%4Ro5&}tZ>KwrIG2NAWII3hHc%=S#dy=G7{UsaM0Hnp z>}IjlxrP5GQ{e_G27MogRSD4~bqdYku75%jbC(t4rK2MvrawEpCp5H`R^U^%ZzHf5 zxL#x+4)`s5S(t&eFH6|f^wYz*TP(ou=H_{xE0@t$hT&WO`l@yLHW)yZADOPanp$_@2-P%ITi&!M<*<-eZ-X#aB zPngKzMK`IWEnJw45)uDf@I*m$f_ZNc%SJfWs?j4%|4(M7lWCa+_P^SRAgMG&UbJ^C z6ivP0OJPfw0*pGq1 zMda=oux0CD`7A&sYG^f>oZ-#Jqt|e+Xb!j`=Oc>5^^H`H_W{5MZ#*n6?PMw!&gi-n z%cNfe#Pmi9vW4!(j+Uz+i$ZrRkMe*rO7KP^lD~$r8`wTVZe6_>jO>c9yVmqC=h^`Zs^K4V#=e zxW{5LT+F^fQv1s9{5ey!7_L=P>Tw66h;y>*EJo;7$WGNn-)0TKf9WhdFC|(M?TYH^ zq{c*%-Z@Z}oPLkPbU}FxbXMj`0`lY)gqaYn)sy80C^vpP+* zqAx17vA3-zOWQKZ9C%)>8KJ|7sHoA+lrEx+zX<%ae*(lnA?kKp>aSaO36RQb?uZ4P zLE;gdL#d~RMAtKOsR>-5WJ=r}^d&Xn`0;OSnu^_pe}JZqnFo1rih$C^%vNm%2e-Y<^F>P;T8Rf+KKabg`VxWZvqa5ZPmaW5l9gk=pTg^ zV28;`UHXK+$)!Qv_svCk2TTz>4(Fj*w=XX49l_}Y3Ph6*nao};dQ5H)>S{-mXZF^^ z{1g|UOK$)%!?qpbE9^~8AK=af^*W5vPTe9bF4xWEum&SPENd@{1tgVy`w1K1PyNuO z#JhMPwG`iBLj-6%-=V03C|;18O;mkvmcvrhEf+p7lZkJ!u%epQaDL{lc?`D!ybhOE zw>xF7&>=yqQLP^zoYJ-s++VufZO5p6q7-(o zZ_GQn&Vjey-D8<(I|2}3nR51#{zG0b=K6CXbDrNL>$rDV^V<$tzkk~G8cM>$JcC6* zH(0*mW~%-7oX>1hglx_+P0c1FBJn}P5Zj8-e^6rzhx%dcR2bWX#xL6AzUe`GYbhuQ zEV$D-Yc}Z#yk+yGxgHOx=&70NSI0xLB(+7v+JoBFV1Nxl@sZ;nO&1E z|K03zHN*X0y+o{@*K}>VPea+gd&cMDF28`AOOZk8u_m%@Xy7K*C@-VMnJ!5133Hn1 z8dIppv;s;KE-VFfZ+sEkoiOYv*9sMLW<5#NF2BL#Fq7H6mIl|-#^s;=* z@ARr2@)JNs;IVK#J`H;w1sD!~C1^yAA8+}4E&>nu7ia?tI^zOt=v9TTLQ=3ZBqYi! z00lrIV$hVp;GR<}V8VgBVux;!ZUuGXCm$dqAtk63?kUoX{;x&2T5ql7X_T?d3Qv`8 zm?l~$jQdSg9fhcTdHLRna5>_?H}XZrTOv#5V8k6fGI<^5 zs)QQRl5VqXU}I3rT0=PiJ<;05#EUaR25X{>MYYReREyc>e7Ze!kWXf9V1&rmiqLu$ zOcP8*ikT82CN@?hq-T0_iYUV0x_L7@Mh)rqnrmN3e6~1_DmqAlK)nvB2Y54jzvluu zW23n=V|2!eUV1}&L-~;5wL|@8wwo%+(I%f2qy;9gl@A}@7Pe7yBf&+xbfL9%WTP0z zDtl)y=+1TDzgznv0`d5G)RQ2kcwD3-V9jB16g5w(tr^}H!TmlUZa%UtTzSOU(lcim zjiZ3&2?=37#`U&vg(yd@dD8rUL^Q0XZ&Og=5QCs{PnG&EqddZCwodsRLGA~)r~yae z`>Ay~jkSbiu)9Yh`Ioa@-2Efi0fw*n(pP zz(;j2OcYj-O7pIs-K0KoTDg)ssEc^jS_BTIvJ2Hv=+)2ZBtBFZvW4)|^`G`<`|Kkz zBn|NN{0hhI$?=&zJLZbJ3meOOYru}omcHF#DgsfRnD%UUA(qcB5z<|xcNrh9Yg5Y@ zX2;TC6*Wi{WcOq{`0%IKul3Pe`p1cfol2vc2~L66Li}sqyfN>CV0%EC3>gSvQ$+BtDz$K26!N#GffYrL=%T$0{pDC{19ZiVPg?KYccKG1J`pFj*UHr|un z9_|deRh-PSTVf+IRoc|I2p>kS95J&RfY2Yv08TdKCPlSL<^~{5sAaUWDe#-VUUVTp zn#5mV^7^~!lSGNval^tS_3@OfD5@a05d9?WFSv}%n#{HUk-Z2o(%faWNe;865PAr! zy24S0w=moP+?Fj{+TwmxnTTf9x)~2ZYBlx9fhbf%IPgbNgmQ`54B?5k3C^$X@)zTf zeDAoU6Kt(S`3V#1h2#$vBE6w|z4qX2@kE)wYP6od4xBUG+9W3oNGg+KLijv8W0kd; znFm(|@Av)dS99OxL)YNpIFKbALxoir6}Q~z4^ zeCVZ(xj&W{K6=!pM-Nt1N3m{d5h~AhXktvP)tV;RAtH}Rd@yB<#5u<&um6;I=d0dJ zXeY?gA;Jxua3x4$IbW%%;*ba2>?J6;-uWsLS@rwxEETk+^Z%o~Zv33PRct7>VnACo zXdkmnz{o;F<(_!3TbR?RI(^C|lKjg)d*HV8r7OUc^S^x}Dm(fyCm{p3Y zL>+nrBi%JL`uEwLe;%eNC8tDg;ac2fH-+U8Sz7Drj!vvZOCpsf+Xm-DtxN!|t~MD+)9X z3BbyEpDI*8U0iN0ya)j)pia<#FSP4wu?hw$vH6HAzK}H0bcy!UfT{89@W>|~@&+%W z@I+)kf_^QAcSD~64x|&jZRlW4q(3Bo-M=!?;=xoDR6%9k`ARF|r6QW*OAXs?9?H~4 z82cC#+1aUN1l@64)aLjugj+XyO?yJ=6(+79HjB!St(BFbaKvb~5nLM3-tBJf0(Ros z2(V))1#nSsA-_F%>4F8S;IqS~Z>ReV7MHxzH1qvvD}Zn_KFWb<4`@dPjUe8>Q&)qj zGzjb~(z`*dOS^!+04PAC*%SIya^)0CquJf7LCgb&|1rGzLQJeUca55kP7CJC$A%#z#phw-GsjG00$X#v@k3WKxth~02AU2A}+{7y6h761NhOy>pygW-q zCUgTK9<3-e!-cxN?Hu@abvh0ig|&g}ueWQAXK4i9A%P>|50Wz`vc_X0DWbbu`geS4 zMl4E*C#2-O2yZa4*~1dIW>J3GDV~Effeegs z*6S?)tSYUw2Jj#D&dbE4)A*9|a{0^L?$w3|&sNSNK%)Pwyn_|tApC-xfgLt7e9Fww zaOmRicKRds%E_TDGNINaGS8LUuz@&;-Tv|< zq34^9QlnK>g=AVN1_T8yU6^S%bEe$5ah}YJfi4U}vulr}UUv$0GxYT-BkFSEK!Z(W z&p=Zm4hAk|PE}1!$gw_(akO;tDFL;4CQZ6bOjK3IprILi`uFPJUjx_hTZPqe{BMk% zO&+V4c~U*v6%Cp6)vJM8fdLl6D2l@Uo^9G|+A^Vkt!KgfUI**i@5U2U&%(RZ!wwyu~7`~b25 zFWHY$H25D!u&|KfP=^Rl$U+FJrTPvFxJpFaRs)KdZEXCzyq2hs90EuMQP1jSqC&Zug%BaF!XJ4S_ zWn@4=3QnGqU%{6X>Vx1GT&lKowYgk@D0;v|cPl-;0Q`Su$GxwN6hmOL3JPsp8QPJ| zMt|UQQi)+m83}ABKv^f%UP&i-DgBuB-h2#fV*JaFsL=_zTX~0lG`T=;QhcEx6I0-iBQI<9roUstVp1%4Y+tzv zxr6uVuTYkrc`7jx#Vvb;`XPVEAJ`6V_c1`MJ$(Ts91#{_M08Oq$tO1~;#&@XY9<^9 zTW^#~v9ki-0c|e^PpPhIrw1I&ZZMq<2@{Zwc%?-rjvp^mj0ciPbDLEG{EaooU`OrU z`xTFb!D3vF(VF2Ac}z=rj)l~5y(39BRM-I7uZkSu-}3sS?2`}9Qv8UpYe?o8?)Tpu z)ppJ7`kc~$uT0@dt(l=CPtG}N5pNHjGk5Mwc7`T$o)gBOB|9)M<^^-Sg;s3giRO#B zL`|1L90atSCr>jG8sgHZObE=bYSc{bXv#zE{9UqiT9HZ4oJL>2wQDELRZ+!fAGD;| z9b)H`EPsD86JC5)850(-t9-Zs#x9lUL4;9*RQh$* z(;|EtGDP55(K$rp( zkdy^(MB0ke=~UK9m;}(4UQ}T5{}8!`gKyvl6F$6Yzp6vDXi0;)1<(4%B-X7Ngew`H9*6 z(rJdS^1{)oa%-@A@U!f*9V=#AFjad$@Pu z@(WL$+?A`+)O~P!CVutkH{4w0hmPzBofu~a2c?TOg8YBIdh~>TV5l(9CQ>DyaFE83B~K|!hhsvR9RbCR zc;Xtt_~V54hA=Yd6eyptmKO(3pTBI`>8p3g(`gFBcdNe(+AN?ThrWl-Bq0IGq-~c2 z3pAbkSyQA)^-CF+p~KfE1|(7WifaDMU~!1Xo@>{R^j}~3P~g=fTt;c7LUl|RotPMM z39LMC%Irfv1kM7`aOwK7QFk6a3M+Ohdj0x3-Uk1W+`T_bDMOLHG-$HIvZbk_|KJ;- z++}H67Pu25scfIR)Atj~ShsrWcIeb;%t_yNZ6Wwp%T*i|zUN7}2nT4?-xV5)?xCt? zCnk(NO8(f{OpoQGiQ)!#7E;>v1|!ZID$EFp5B(6ExHK_J`oLnf1H#I5u)+p|J#H>2 zIJ?!VIDtjf=4eiu^n+>w79Lz^#SH`cA1OnyfE4~Z0d@d_BH%&7%|G8Oyu^kdj*gz` zH)gb4$gHuMp-=Pklkk~s-bltUODr*%;)RejZfe?BeESnIh(*n~237nwtvHks>B`|h zST?Fn{2{&;qLz8x<4c@xLNdY-DA(m%aDoJ#d=UPlZ$hyl`2fr6u|JC~yC zMxnRfF;0eJK@n|FEI5DnY{pQLJin@#WFrhpr>u#qclFvtuC6wAv8!wLJ5L6w5Z3eD z=|u30&7=^f85n-IkEfxCQbBj=ZHo=*4oBgI}q&H4-Re4*wU*-U9XFii6A;74o59s1kuK zX{@WJU&c|hd+^`dY;1Q$EHic$i4H?UA_D^|_4U6-&6+-Y_U?Q4U?f?5Grfs|#9XB) zvUN?{^8!+M!fpQihsEy~(m_Ea$W?@616`3wjC8);=2*mV4}15v;X64v7%zHjzi~`P zXXwGy;C@s-+G3mq!_#ry>84X1;!EwvzyiH@k0U!_*s!>c+id3TIqcoH3QlF@=M2w2 z#O6ZV!!>HiJnjf=?2i-EJ3tc1J6&%Q=FWlMZr0PY)nl%~%Us@iPX*{lfH&Wl^ zeX4UGW{_;P8=8LaP@n!Ymix|kj+*c&v*^xT2^@Wz> z;!9o6T)s@2aHYJE=@Ej(CrNyNrFF9)9j`HY^7`iUm}K+-46b+m)Gpu*xdEgpr!@0* z?%gr+@_RogSsWOuzBrjrm69@I!{rfI(r$?x zh=#6VZy>{zUv@8Vai_dTlN%4_g~PJ8ll<7^onmw66?5xeH9R1QqbI9j0Ie?aJ^ysX z7(eGA5F;ZFRh*~uNF&JS%gt_bUboq`!j?n$Bi4>wJX}+d%xeL^=BI{Bh+I&b7l5P+ytwQEGHV)t4_> z#AeUT#QqVRnq0+5ryo&E~>i2^TNY zt+p?>O<^bYH-8(S$wPdb9djb;$*khoa}&$zyhu|SVmh)#>OUNIR8zaeRQC0d&n_yh zJ$q)smWK6@dJ|dmu+V=5a=1L$Ea#Euam?`5&S`gSJgu&pdfh%M`O4UokeCPpBG|@D zm#4qfO>4jHa5z0+C$uC*qW1=GHvaR@v$BUEXIt2P2d%Uk#Dx9)$+Skx$<53tb%VIW zS0J+A-HFEWVGSBT?F>u1R`Kbv`H|(%j`amc`cuo|1Cdryuj<~pvw79i&AevpA_mIw zsET!bjQ6tLBamqWIEfd&FqcyVFm^)D<$%tJb3<1}p2 zr1gb~b4bGhAiDMFVPjV=yi&LF0-|l127wD8Qrn7gZ+ikVKmtezf(%qJ+y7CJCoHqq zu9PF;E&p)mBp-SC2K6PiNgBPN#={X6D*jYNwOnp@V_yz9v<)EAQx$AR+Y`GvB;-ME z)RVu-kZ~aaYE*Rel|>F@5d^=r3K*emeMcC_w4A4ihg(z2z-3WP76`ypN4T_t+jy75 zsTYaLJ8^LTJnwHVN@+U{V-MMx$`Sf9Dnf7QlG-#Ar3AS7U<|!KI$;eyR#gSX3@@@8 z%-j_h*gAl|hp8kG_~Xf3b%ae61uPd}vbHDI=%AgcEq9RT(4j+A&-o`_>&Ow4b0>%> zSes?FvG_0nCrVH69kb&3xg(hKHpezG`mW&JR;SCJ-uu#K)=-Y790d*v^STIRw^7*#1P~2jD7O-&6}a(vbHrkMVC2%mHb0 z(5NYGFR|o5Ut%7!cbYFAi|#P>tCx1zsI}zDaE-=c(6kTl-#;1> zVgUzpUZ!t4n-Ls*pHd-{Gvajx-Wa7&me+jy{7RvcgyaTjF(;k0k(3{+7z{gm!h}?; z*tzLYptV1=zo&VvVe5Wk_l3w}u925xsZk9Mh6CSO#hDWy%M_ zy1bLfdExtLJ0GBg>J(dl^FDP*^-V^Cq`Yf6%qXA*{7jd?y-$7Zy9UPD>g#87G*Iln zzwjb97>l(nhKnD(bEiP={2W{7(`*e-bW%)#oNR7xF8g}u4duw#rT?CufIVaFF3jf# zLh}=evY;dUCvLmyG6&t28d?Vp(>{>ZVWJYo$c#d@K*3?kQ%bQTWAsbE{e)c9t5+{D zc0xMIjW#ylmRg7(A1U;E`87A;aUmFtbMC5w zr-AJv|1Q-~7o$kiapT5)t*@uuYRNL`fgmQMA4lxpZ#a9TkwLzaDNPGN?nF#6hYuV3 zjLUxu$jf4}lJyM@CGdj}JVh}23uS`+_gW9lCp3=CQ#rWM$)9(~5up7)kL#W{R)e?P z7>BC|sKN-HMn>d?n3NC?j{ zWe1+LL=U|#xXGaU#D@cwe!isAM)))zyw=T)0{>&k6B9ON5ZQ4oBS-eXit5Z+9IS6K zX;Ro?=+x4Zl6pFzhr$@&Zabnr{(0wvYyVm$noJCaO3I&LNNllrLxq$f%p zWOW}4Pet5ozqjOn{;Enynle{9uc{Pi82xHYUqQinGUc0xtTq#%FAI}-sch@6mHoWm zWd*DxM%v19;k4*HSB^)XLcpY!Cg#)+{4e`8t71?NIk5Tc5(HnAi*}z@t+if7nwhG9 zth#?U@z=v13ezj<#UI{wW~VVw-sw z#_occSk(h#q<86GcOXh8J{k2s>_wx=8}bZtw>!B+n_k=EIudrg9>!ZHP6AB%^XNq# zlsC_tKMu@fhRsp*3Hfq^C zsmNm%a~?^^AD5aVbxOjp)~4Iej=NVsdaKuQj#3YK35gjJ@=?3>^a8{Chd10h&~UG6 zR_BqLT08E3^R@T+e5s*n@qnqCNH0PrNB@K#FUryQ@O+4)kK&l83RgRj$`xP}lZ+s|UmBc&N_6JcT}q5;-Uj zvGEyo`D28tK=tYKFiGG`)h|1L{jz^+3$1Wnj@?vrp6B2IDgQU+)=f!Y6(msv*`d)U2UC|kDowtteC_Mau0T(L@-hKs zW@pLt^`8ryF zyr@c1$ztNfg2s)r%TL`!B*d@b^#%cP|75+GZ7gYRX&?*eIOj2SAduxDD|z>2Vjx*d8UP;*}3Dzy}I=Tz*80_6rl@Mc-eqqe{jMbE6XX@xo zocO)SBP+N{2?a;kB2-#3R}@|LGz0q)s&!MRy58IP;YdUAnu1F!ihf+Mv~q7QyQClE zTbFme;f)rOajO%SJ&w-<4J(H6bE~iHR`QWMD{}}E#OphC7S%4a72-=tv)11qbp0D| z$sRS28TE^np_2fL>|nCW2U3rL42A{N_fG_zbrfiAq@NC}^G2;wQSz26R;>@rmpkgU z5N6qqrpmV*EY8bg-XY3oJ>3a>@qvgY8n-fc;dZEOOhm+*2^lLd=I1EcrzQeCmTYQp zl$U~z{f5eg@Sd?#w}k36Enxu&;DpaKE$-o|groLH>OdgT%Ne5i8zTR)f*COqW3Fi~ z$J{=5^7%}_I4#Z`i@Brwp!G#7t_YEAR1|)4Jrx-If6r~xWH|;Dud?Xj9sfY%_~ec= zcR%lq=EG9_Cf=VWK40uH=_V)dItP&RupSOmocR*sU#JrEF3i7y=LnCOvan<9v=hSl z%Z;u)s|ftwb?rI2yMLOeyO4=dP!B2pDOdt(^<_>)6k11EZdGp>+=m%esoZ~<7Ds6F zQtcW^7Z80a9CKqn240q^l4L;pzJInCYSEFz4ho#oaqXmU3zvuAc zIo%42{sCsabuHIa^ZmYRtNzE6b$!5^gmPXP-(=AEx3u3ItL-G z|GLrBPjXH5=1wwR@3!>=2L5vO<2l-^gqgRzpGQXRZEIUc>G5?GwAzbz>+JD9=y>H3 z&-XRE?!sG?4iFlRCcD9)!!usT@^JH<@12VIT`or`%pPUc-X27*57)z!*U$X^48rev zd)IqhCnxW!6P2ei+Z z%U{%LU371MuQxsW!R`v!FUFf}c)iZH+>^m^!UeutxN7dPgrnZ>@M?h2{VG6s)ztEP z&{pqSudV{wL>Tp&8|N(waXu#4{(z*9K)h`4_8vo;>Yte99v-NHaK_s69J&@{m1#bKhSqJ-p^YP}S0x$?v({ubEF% z`M}a_%J+t>)=g^*w7z6m)^r~<(R~69#*KaFx;iqI|0WHJ+-b&+&7-`bGmw%Dme?k=an_`Ni1OKC$x(@#w=$@P z{viE!{RRgdkC7KbwxK;hX=R_l9f=W!Co>^%2*J-&O6|BM?tvYb^ z;OzPvon$kRDBu(!uur*6+PIJuW54qQuMs^b5VQN{+Ro+_JV^ zcFhadh>~h*-Cz~GnbF9|{VUGu{6p9JhWoct8pfWzrjD|A~ z>B)-H?L8N2>}shKK9J|MpS7X>#iXE>MklHFxTs|E2sev2o&n1Maw{B!KP*|>8wY&11@=+0A zGQOFfy|wYn^@d~TrE|p0H<#$- zrX4}YCZ(XxQ0M_p^lnxV&Fncx@LPH}Q$0#_n$VJcU3=YMV~$2)S4GY3u5NCmj7`tx zc?8!pKllU|HyU@<$4nbS`0ftR)^Ei}HE@4vt&a;--)S>*U6j0cbP>LK3hkCd6+67m zF7McuF?ERmvfkAHeCQ$r*F}rAf7+$xRJ{7`SkAGh@dq>q9_ak~gh@aPZ&ZBJh>Nrw za(h$g;6W`djpZoK{5Aeq{_IpNmZ1;!T`aQGKS8skgtTGrIMpvV5PR7DrTNyJ!;Y(R zgRuq89{#`PQKLPs1>v!XKr+UsCY@tpVzppLvis8{olQ+bKy+a7(e$zqEgj5qu8hwa ztj~@6c9%xIqN6bWIswAl{Pu4vhjJHNM+{Ukt9I z{;>&0!R(qKUI3FNS9;wR7D?2UgN^SE!0nB-rB zxOJAPX^75pU@YG+CGh7Mmj|}h_$Dfw5BrqWK52a5F{Y`qg?obAc>8#^ib>;LMGnB; zBS)HFEjy3Iu3#Ix_Ek!J=X^6?c@A{ww(r1k8K@`~&?n%JeOi#&()6+N7CV>Q&>|G7 z4o*DncL8R9f{or5vra@M(q$O79`Xv#dRd~8$W-*l@N5n88|x%5RSnwZ`^6ax+|Sup zHM60-lEkGJrZ_S4RYK24&2;0?zPW0e(N#7EZt&oht)CX_UgJaev6zwFOL@+{igfB@ zw(F14=9ZRk(9YAhPaDQG(zw3t7p9y5OSi^S(4nhoh_5)ZvEl%iW^Q_daKt!Q-DR{j zuC4(opJ?&C)$Wq}Q#}8O9Rh1H@8#(feKtK<2U2YyQAov|1gF#`bKrk23|}Ye{P%6{ zA^$78R8S7XBAd=v9ef{(zwM2AeMp*Gnx1Dl;qJnYqLWx?=-4`9bSnq>oBQe?)k9 z1Bf~?a`;;NpWb2`!*;f%alOlk*+V|<`dFO)4I$reTcg%=)2dsNfIrNCe%sM)_gwmT zNH!dA1jsg5&J0_R=5CVZycd|feoq+eyf*PhiSM`joTKADlU5en)!YFD%B`m<+~(9j zc2DOX`*`k}a?=GEx|j{V`RTVSp&-EuY0lMcSw)C1?2NVIfPk{Uj#HAeCfzfw;f>F& z;0QCFpM>xsK4RS2&v07tnb+1<2{$*bM0W}OhPpSyXwD6)QaH4F8_mG#ClesWmmY%g zdb>V*%=OdDRVlAPY4z{eJ`?|AsHI#oMCsZEw`C!Mt_fARwFTU&{2@QT__u1EObG0m zV(s3{{@XfjeBY4SaJ}*Zn#m%_zDub3s-(RQ+?sLm!emGqL!PW5s9rsj zL}>iU#exO#D%hnyXWO*6HMy%U4{?mHAb9JhaEU^$3TA{U9Pd%`SwgESHyJ zxa|s3y|o1>7V7@`lu~&V<3RfwS1`xn7ZLi*SE^d&iq~4KosLly#AoL05vs)x9@KE) z(19oVMK)OAy{NzOa-qe99OIzYhLx~a`If|Rit=3o`W*gaI3y`tWwm@ifA{uSB6$#I zK){|?2v>b>byv^kilrjWHPK{l1@G{rnxSD&yM&ty`Z7R@XxWYmz2`NwJW=ZS2ij z0rv=sN2EKBfMHBI#|e^D_>={!Uv_`0=v_V{R6CipgF1hS=dJFqwiu9ENL(>RZqXBa>09mNqy0~zw0;kEFm1W znQE2WU3n#?!$=NCj5b-QOu~C#IKtPjLay|V zBG;oVS)WfqLX!A)=FTPfD(XKIpQpRi9ot921-!Y-DY1YNa&7K1M1AHgDO)=`uW$F& zbA6|b5$FaOS;Fh-o;hfTB2cKQ=0a*mDiU}|IfN?|86IviwSxtV8tvqL3ZW$WD1iy3 z_nfgl{S3H72*Y9HWR==cX;y#@gHd=lkhVITN!xZY!~XDr10XOSHq{BIr>QQGcJ6Hh zzZ-s|(1NkJSx}7R|KEDB?(r-+A*sE8jHdS9-*PV9S^e7kqmVJaTR<@8^!e4rFCT$a zUW3xjK7F-imBTTX+Ip|T=uxA-*S!8^zR|V2WRBS2dG3)iFa6uH*AQtw3R`HOHU-b$ zN!ItmqKfWc*6r@ByKe5a^(zPggp7@(pVA($D#RkJZc9r;mh9RofVS0B8j4c@KT-f; z2$+B8sQC4&-_t=(OUs9b+7Bc-5Yyl-P4am2JEyhlwrM!+k6@Z)Oi$8QmFe3KY$D8r z`uL6U#QybX^V#x0HBC^}%n5%ZX#ok`fU&Rgi zr?w(-SE;CUwp1t2j-&$FK-XH%%s`Mu(;fI~K{xvZiyC7vT zQ9y@3zBc;?;H`@{7psp&7tz1L>R=F(vI|p0qQgtt-dwb59I4v=ql=Gj96gM1)0462 zYlR?QlzV}GQw%vKwD_HGLztX}hL-ib_TH4vEE zNE0=Bf-wtvx2LX(L>h{JK75ius(v&|c&oazf6>gpU*iApyZ--QYl{n6hW`iaHd2ng z19lKyhbv8Ii1Au!(W*5x3hGCT^hUL9X+YUaL=B(=?XOg1pQmn|%I*qJhiPqD2LHAB zYoHPTdh4|YfCJYw>XEgmgEGlE2f?%dB{VhqIR32%58jax+gteC|7QpP|NgJl`Zok9 W_WqEgx=Z*BvkXl2&rO>j_&)$=qd1WO literal 0 HcmV?d00001 diff --git a/docs/language/learn-ql/go/dfg.dot b/docs/language/learn-ql/go/dfg.dot new file mode 100644 index 00000000000..82253c9b133 --- /dev/null +++ b/docs/language/learn-ql/go/dfg.dot @@ -0,0 +1,11 @@ +digraph dfg { + graph [dpi=300]; + rankdir=LR; + + "x" [shape=diamond]; + "return x" [label=x>]; + + "0" -> "x"; + "p.f" -> "x"; + "x" -> "return x"; +} diff --git a/docs/language/learn-ql/go/dfg.png b/docs/language/learn-ql/go/dfg.png new file mode 100644 index 0000000000000000000000000000000000000000..6727af7b4ac3bbd021e58b3153e4bfc7da6c434e GIT binary patch literal 34931 zcmb@ucU+GD-#>Dzr!mO`<6&C2498?V&+KDV3Ixv}B|~OWKo`N|Y8VEt=YBYiS5A zZS^~@yzlSt`?&x9Uiahn@mAM)zRuTpK9A>d9M98VQ(cj2$Nn7z0)a|dNlu$UAk`%h zNTMjV;9rIxvOD5`$ShP9

    +Z|4S-O4<``V2+DFYx^8h(eK(}(7B{4(4>i6#S-)qm z?+za7JuN$moe!oIetq+!=+Wml&#!dq|26v|o%2@Z)uRA?-YTAAEvG;()m@f5wg_5< zudNsV9`jl}%f`W8XC=<+-M2bh_SS%3vGzy*a7VETKM8J6AS6wlQzPH}8-Z=7lGoTU^R-Tay6_WyUkv|o)pX=ML_19rByJUl$M>sfhuVIG;!pFdAc zy?3Fjw)R1d#V*q1tgNi`bZav+Gkg2&+}zys^z_`^X6gCO(WsEtX()Dn`7$;#GV=ZV zclW;E3F4kBuV1`)G?8?-v*fDv z4dQ39zx3AI;^O&VeX$b{HoqBlcVukin@dUVg;EtYH8mwACH#5z?5LAySa*rPzkfnP z0v_Pit5-2G`%BtdS~Sm}kC$9efAi)|NlD4OckeLj%uHo%#iGJO7BScHm*!RC;^Mu1 zeFX&thYPGXZ*k9O#E*^QpoGNVl|Mhefzv#gN(=rLL~7N^3cHclRnkn#H-fxy8lbUHR#{Pqz{8 zU=~t;SPC;1fTi;HFS)hoaP{idw||6%h0mLq5FfJKd&BGR3T9~EfddU}pB~xR+hbDC zrX+v=!jNsa@pZ)9ZTeX>hiNQu`>P2s82aCcwn%E!+oVxK(u>|k}^K&*My z{m`n5WR#3aq@|S?%Dv*FqLdz4sVFO7E;?V^(c#+t`m&6S%pt``x&{W3XG4frB50?M z)M;R*Cfd_+snxaRs};gOr=~nGSDv1VL5$|s)||1^j9Pkn5m8ZY!yg`ERith$s7(h^ zW2d&KYb2h!nwFlV z$6JzxtUo=Dj4aao_~FB)%Dda?IMwI>{ISaK%A?e9a4zY^KosPOABkHF**RHf&Y$<3 z`ub`o17DP=^T9V&#AxATp%pfgo|-y}rCeS3`S#imedBBP_V#HSi7b2ej0_ImW--}< zQ<`x4#;>Wa{9qOd+bs1+{_{`x4D-w?w&>{S7=9olJ|vsSJq<5J0cvJ3*KhA{$Hm3z z^G3zQkZs%66nCn%`-KXjxKca76LAapE^;vBB1I^Uh_@ z41aX|`m&;`N_OGZW+0?cW)Dxq5&PLw#46?W4o7*T^HcokV@9uS*4LKnB`(KKb$qiY#gZuqkJ<4Gattu>n6kJiyGv#JHWZTid|k z29`b~B&4lPJ0UVIKAwg}{6Pur=KW=6qt={CdY>u=zc~N4FeSxzEcJ4G+LgXH^zpqT zhS#qB!OGm2`Z_Z+thnNit+6~ewlUjq?8uQLYBifH@m%d!SR&$ud>}(#$yGn=(%9IZ zUwv;CA2HP_>9Re?bQIWqNs#o68Qb!sBeNZW{!(L9g{~R#?n!ybm(v?K5?I59-vf!9 zbH`7flyaN?hBzOx%tebpfxq>?y%B7^qbwyQC28}c&w6$z@#}07vu(3FCMM$E>uXU_ zj0t~k-@c9YLcBHO;29UqqZ^*=%*uNHeEi4hYm=@xV%Um8^o+!>X6!GqSuSxJ^bHK$ zsqwu%$GE7txcI>X3QNfyh-X(?Q{=h1xe?7$a*y%w%q}jPmbh45ym&}wa|ipVm=}+x zXJ%gh*iWoABWdim0&>&SVpE`AiG zr{5g)mJe@A`$})!c<)0Z9^H(C-`>`Sc{$$q{s>|Ni%FwV2K?mFY2| z;`gMvkGIcWU6|@RR<@K1(7luoIfvt*~i9fHK0BqGKElz zw5le*nNI3e(&{vHblUftdN{AlUtX!-PIm;6q3!F}bC=A0){vdwUjJ$I_WBi7)tv=- zw-$dP9iD&VYR=D39JJ<{JXNp#`}gB)U7Hz_U#TB$i2U7MpnCrNd6DBj9&gT&J*}q-%Bw9& z(g6VhA09CibC2!A&`>RVdp@!|o41rxl332n$%z**uf%T35dQGt!|~(CtL{^UPddx& z($m#lT3v1Dls+ja_{Qt+o40RI|2I^ZkY885fZLE1)SEqklpOls`8SdqS=rk&9XN3M zQX`}7Su3m2V&`FPZSDUVUQtnTyCQ@5bkeQLuSUmW9m|rfB{9OtW2Oq}-*G_lxs9dep1pek1H8GJsUHUcstkBzJK$$Cr0;8sl1}1Mzr8Pcl*>wkJL>};s6Y)X-MmH^77gm8h&6wJ7Tu& zWMGnTe_XMd;-#IHC6|E!_X(K2_oHE5UnJPtBAYBtOVg=}*que!c|HF@Kztf3KXlyBda2kGi>mja@D+8NW)ox$VWXmY zh-i+Kt!-C^8zA=z{m*aLaY!Mu?BzE}3cx6$MhG0AK76>pKAjO37G~A(Xv*cE-%I2LieuGc9|ampAETPsoWne(^)e)v=5rKuExvCNpv3capd`T4wXD z8W?!y*eQm-RotodkakCac64x1r#E#sY|k*;%N)N#P9-`^xj zNMF8u`L*!M0X;Qk<*ssXsXH^o>-waO+Y}Wch$Gax7^uq7Faj4OukCDva-6h zFl8>nLA*nVH?!^Xb_$B5BR7RaL_XEm3m!ins%cgq)G*o)^jaUmtE{XH5Ch=W_vRY1 zY7Y>LALYJESJxdESLP?YH~yY1vA48*93TI%VRQaSX{DBx)zyD}$z?5AZkF0u`@1-x z$}f<5ZFzPSkXXul{avSlgoMON$Ns4wKX`{T_Ov!c9_#Dv6=k9}?0t80E?8>4)?SG? zIJV~M-wTBpHP75}AtB>3kCMA*w2hjYnt1iIqXf*iL@%pF3yuQU0~@BMrWQH$Ax|8n z7(#l-c3&TjG>xLxCz+pU=M)eK;rTUCUY?wMyTXllY3Wb?U9-qHm#nP;02CQcUg>`A zJgnePmS!)?^a;m;|NI*{+PnAfe*h3qKO6f&hZAKY8=FsD@lAv`q-%3F&3m&$H9PV3 z=WaO5_&uS2JE&IZxUrYl#@`z}bFFP{M(^BSjhxX|&oan8BE;&;M*P7#@yz+tajvhg z{vMe{=sbSs>f4otpR0A8iJCP7UaJpF&TWpeAERu?votoUxh%J9NJ-qBeJ1x*TV!Tt z=8!@Vn?^xmqAB8pPyJJchi|U`+%H3mFn8luZ^a%8-}A*z>=-c55l+s2k9rNe0+&uZcHO?XO?IMu>10$A+(O zX-^y`G21XdV+h$rY^nDG@k*Nd2RWro_)i`@=*!dQedA2l!p|PXqv1Ml3IZklyAY>2 zSi-`RP4AvMbqe6iOkfj)gc##X*p4@E-qdye-Wa|6p<>rN&s7mY!7v`6O2ep}G_~k6 zN2T27xegzepAF>>B^F=B#hNwa<2L`&4x!|*%d9MG_5jd2c8Tf<7Arai1_gFB5iezYk8lr?PIw+T4%7=Ql5}gGO~^6 z+uGXB*DHB-kB*Hg9+d)$#-me`ZI%GD%C9#oCfrIlbUl!6NmxWg(qk!vr|@(q33I6n zQk0ffD90fkG1S+nAx2z~+9k#|3qdyjCuoI1@SU=dhPxjfr*Mw=y=Rq6$3hyZG8 z>Pp9+RMoxip)tp(jZ$-Re*XMa&nuP-p9gdgW{~ zBD4n&OCdAY)YRx|JsVtoo|&B;bfKfQb(fcM0&%)i)6#Hw73n8}hc?j@o1BW*?A%<5 z3BTU!f`W)M;wtyjM-`2YjhC*3u00^B+YC+=Y-eV5G&QA<9sp9>zh8x&CG||=SPbp) z<-tr79i2lM`F@Gzy5?qUfz7-ZB72ZSYW@Q`>UwU{r}p4P#%rEDVHhmB;^2_BH`I1V zRbyk2(Tf)^F8yD>56+__PwC>K-jmEs?$X+JS`J1HtCePVo4^+@_zTp^O*UtnA~Y=V z%^NY>=yhJY?#l2rU@nUCqZ(Ex3bt?k{|77U7)X10NHF5w6V`pQvzwc0%Y%?L8(UlL z1|V;33WY9FF|oEldV2aw$JN0qa`#B6<27A+)MA0eK~X=I!^_Gf_4Z7>ik<)1F+MrD@Z*a{SSUC5ik1IA*3J#1bp6#EZG@_{ zROxDD<`ITK`QOV6h?s*#XVulyo{-b9sIfY2yOL}jG~cj^*L`TYmz|xQlAe^9yikfS z*43AmCKRlV)X@!|^jKRuULcNwR{6uTcjH&=78VvL6*l*Yi_+bZkMG~VNBZLl=oO9q#1#zx@n06ms zPHsM>u#vNU3owm#JBtZeJ4vo`J@7?92ZtgNkA5OU_ANc$_Se_-+O<^o1Dj7ALcHnX zZ;hiMuuh&lsVc^DxZ2_sHIwLji&qrB*cvNHE8D)9mU~IuwCL>U@LK(O((rD^p7A=G zOJtjH%L{=NVQXX-JPxabJIB3{#|Yqe%GPF8U6!l;>2#~8%fEj83TzTie1g@Ha1Be^ zgx#n>h;c7qD;cF3KLhb8LUeGffsjy2r3P&As@@vh_x6TH%n5%s3jWB`R`rjUmfY6G zkdUImlteZhrmz6NgDNKM+T$I(!om@fi*JI1Y5toL56lRXQb&eXhYOM#!t5o)6@VB{ zPN}7(nPJXE4?$cC(-N`y!L5D=9xG!!-*x1h8Tt-BbmehG^dJx6DGP}Ux#p%JS@{RRX zTn(F$iTYz(Tb@RuB!5Ju4uh`q;p=yUf3~b%9C5mc0aT-TLYU^lZXaQWG zvB(LzjMN@D>7XRWL)bNiXRHaJAIZCYTgKV>cx=<9|6rT!!C>NCAq#fQqLACUV+Y4x z8lT$n;79R-RyzbY`Er{G(Yj_7LO~B7)>%>eT^*_2<$s@)&G*@}XVukm&qZ%7*#9>- zH;<^#KF!Ht-m^!JKA7ngDo(DF5Q3bvH+43EUt%Kbe=8(T$4R_vSDsZzyLwdVX5pytoCFf&U+Zut)r$I(eGM+;i1 z;5wN@M6fvM#Ib9)kLLBC-FjMDGQ@L^1rR#08SraQ&4jZu1pcX_kBeY1y^Eo-@##~iN}YEP>K}9xMNrixquv}Q4~n2e z6hqj$VCx$i8#w|&6GBS>vie;6N|( zD-f>}Vj8B5xq+B4zp#)d_U_L_`xq)gK%L!PrwB5%0LA^UE|TlbPfr(nZ%BFz@7)^- zT)eWnN^?LYs3uJMqdM_2n$){hahY@Zmzoe;Rp>Eco|7Hi%0HQOO>}iTP?BUebar(a zo;`b1SXl4<5e5bZ@QCrE&O@ltsVFHecW>sm+GEN`r2hQ*BYU3`6-wG?CPWT^`LJ%O zjBJ!6luV*8!RYbX+Sze(a70B#RipmI7X0u*L_}oASEl$O;#hn_>}O?ZtHG6%Q|;F^ zG*o7|=IRPE@cYCBcLge9;FS5AJ$t#^m=&UWXjX0fR;Enq`#@+ zhon0@Iy*t+y|DZ8LX8}e{k=GfY*HCH1qF4G0Npv!(S~QvY)M$#I&|6A7NlD6!-uJ# z8)JljprXmqces36Sw#i>O2DH>Ub7?q-z1*uFlG2wS68Dxg&JiKNucw&9;g{LMN$Hr z5>PW92F0JAo*q~r&t#w$koj0)9C1WLpb7j0n2m|r@6Av3l+VcOvub3jImZPBLB)c> zM8*IIf(v4EVg(fx6z~`Pi4Xq0!xz#CU-MR_;E`}vUq>@{XbvFF8nJi0*fiZi*Na}C zV$_@JDRQ*1NJ&Vz@b&=k8*$8exET1d-(O$diSheTRdtAuFB|++BN-WiC$MS|49eKp zSoy6*ekrMPFvbX9_%kCT=&LKH7;9Uu`}rhnTk0B#DGAAKOG0k4(G>%q)$mXIH~MePmKIv z*{)x|{`vD~9INwhuVa@?br)noo@!67*uZd50^-3#4=GBzP5T%PPfXnWGpT3(t7|JQ z=__K6<2BHh7m4*8{y;@TL-Xp!19j)59hiI&`!9)wJomY^`&0+8)9?4!5?Y+GcKi12 zL(ITOw^B!2yVBLfMGj1k%3bhW?h8{BQ&YXr|I&uF&x4_&@O4}K74PS#=-|L#0EYQE z@XeWgw%2yQ`%6(>Ck5~^{HVOQ6KwL6j`db<>c`qyRFd{0J@xgI2twk#t)!%c6rQ6; zJ=fQ6s;H>AyNgB7?O|Y08J6Z_XaKj0Z3sZdbo-)>O$Jm`@S~UV>zq#`n1bWSw&}1@ zID59KP;4Lg`i{?^wQK6@RjB=RE?iK5L~ZNffW7HpZ_n{@Z!0-7enV-PYX81{CFQX% zk)?gSyu3Si?zHXd?d`3tRq`TJ0aDl1*AJ5oBQhlGe{Z?OX`?Frr%hryC31GhB3&ar zfz-gqXhd!~D80OR0 zJyw4fwMo8kiy!(Bv=6h$_46x%^iaAhCO0V;Wzb;s;MrPRNCL$szYs-P{u-c|gedFw zR$E6Wzp(Jgs(V*YPxu}4T7MFph{xIfPxJBwae}}my?iNf>{u?6AL@I2I5`!ae(xqZ z$M*z0UD8IqUEDgjmrXCgBv>4Gb>)B#9BDStWF8(K^$iV~!a#tO?YP@8 z`U3e7($IXw#&WZ_n+y9s>2y)eJ-!D#mSSDya%c!Dx$oYs0Sj#3z8(3Eh~}H)S}R*x zTAW;6U9VsN)%uh?`X?$Ge1<-X`Bk9=f_kBv}-O90;7^?(;Ui#m@5!iA145Q4y)N?%O!q1`f^lPx0Wq3~e9A#26_l z)y4?hff_~#PVnywyK{t%Ko6#MFDt9};;+7?rKOGzU6Q${)9sy|Kl|Pm1qKG9+`%V5 z|0>`wF#_$)2^(}NK|~#Skct0>oCEbAYEkHQi;EYBQHoDYobp(jmh@ctX5gn}`FM?% zH1x?65!;RoU*9dZ4)K_ z!&IU+TefHlBXkobb6^}q%BwCecL!Sf`};eIp9rQ$ZGgGG2SbaYT!W3Vwbw&vp1$gf zivQNFTdUxIS5_8&^%*~R<{|GojG3~uvcf-Nc6IDd2n*97??D8Ot|82R$KE8$I2!V) znVCQ{-Vi>I?|saMu{4I6y`_rrAv`vQ%7qw^iFDTKSqC~g zIvhODpYOvA62XI-8}wgGS`LcbH*Z#8gup%EYwI753^5x6GfcH?fzs<)(6u#dCZ&wXYYYfU$lUQ)DguFsRq+${c8Qa2$ z1b`=qrq02E&ZB0PocjHH;MceYGcz+zH%=5HPTEtl5`AN1qFl62SzT3iXRRn*T9JfM z_dGW@I4EdsZLay=vX-5tS!hq!PYcZw^LHCO%HCpqjmfBJwLxWsUluc(c;3wClf6knQ3W9 z1O;6n3&x9Gvt3-Rt*Nns_y^V!_(F}GdiF3o`)zN1HD=~`$gJPLUy_$%B0NY3Jt8P5 zh^zFaA3+%bi5iY1b0+ zsT=WY7{!FnXs8X2k2A8eHrt!A5g87nJ~KlAgT3F};Kv^x;)|3NY+OFP#E4^rUd z926B5J$Nt$KA?&Bx6RdrYm&B8NIM9hJP9|Au&8L%2FpPjJG&qEcJ5uDYnDO+Qd6YL z``p_b7ZUOkgg)|8#h2}YHM27_+js8N$uwoABvPD3X=&d<+>UMt06XaG>D9QpvK@y; z1Jldca#DPJylI&ShLm?l-I?GdYyF&;@Dl=nJFqG^awOhH9;?b1w5ty!X&fTbapn3C~yK)Xh<&K-MC0WLE*N#aJ0SkwkQHEMBPg7{EGT|B5^V? zKH{qsKLj+^%B@~fXMQV?={{-F4i>l=Y+4WEs1~jt%2;|yMH?Hk^#ja8$P8-`&eMh? z#80Vs6`MGysy3j+T;Ava^rDekOM1-evwL;*cRBX@@M?9Pp6F3Z?CksAWyjojZ15}B)$QLbsMCuuA zALq`UoAxF+I5+^3swtA^-1;-w38wrUA479`8qm4NvP+{GJCAFCj(b37M#{O?EnERG zKb%bvkKQolR5mug^*P({q(kp}X8w>uBq6vU&KVgM{!y*!?EHiMjZ#NVv73E1mbhRD z77)3>j7=y0g`24F-Oca`!r(?jQxk*&^DNfS4|W}LN`F4w!mYl{Wn&!Rd!LHU5%KI( zqLh@`d!NFx#`w6n>r-Eohnk;~cG=n3Jb3V6dT!1xi@mnK-WHrmz^!z>7vZehFfTz) zH)XXmR^iIKRIUl0vK?Eq^rC8zMtRl)-XOi)s}$%yD8%{TLrQ*GbbPwxjH*v z{&UM%Ru*=meJIGPy*11}qtN=2ZP@<#kPdLZ*V@cSz?ihEJ<(e@q@JM&K*lI^Us(O~ zV-Y&V;G?HgDD3&TxE^ef)5_2yb6{W)^Q^=atkOKBJxn_*FhCG0m1B^(~ibOAbZ`0FGYpFgdO6uwm z85|0}1jD$Yr1W5IaYgIhh+oIouZ%1#{rcX9zHB(Lva+(Rv>dxEbu^ruoQyS$g#-l7 zm3f>>$UkDR=Y>wMsrO%bnu+{o$?!22_k&vZzVFg=3np0nqXQiN1b#uW$HTK@>n-VB zNI@P8UDi43R{=}*GB6yWIjPr^l2J$FAIEJ4a`MXGXTW1r)YN5|o?n>{IN>AoWA%EO zpKter(%8@t7MubU?-NQgwD-pMEKZ~+&XN*EejLMkQA&TEO#NLE?)d~?dIpA1(L(8+ zl4n3y0JE!+Q?zJBM@Qo%+X-*mf5N5(I#x9G%WDDgYnuNeRf;|*(;@uIHga-B1%)Bj zmjW&>F7QV{#N4)~a{a~)DUYR>YbPDH#P?ngfS=U%n&dtdH^4{@b5tB8y7|ZDga?EP z=PzC)RztuMSp!*!tGF|pG8PstoVA-}0H#h((*Oif)FF{!*xLXq&?M_Vd{B7*`;@UU z#GXiCY(4rT5xezVTxLJ#7=u9P`$jrBK2Azb4z=88!Yo;KBuA$gPfbetZFu;pQ#_B} zJ1V)F0m+O!kPHQ4$DTZWIt*7S$0p&O8GD=RDOI`05rIFPT)pQc>hI-1Oql2fSm z+1R9=Xjr#yy#quYogbFA?FoK*ygGH<+=R&E` zbTV@MMGFg#TbkT5?d03XNOaHMytxcSvHaWnz`lLJ0XvIKWa#0_tm*2C-bh@6nFL0_ z3Rl++)$QS|@HEx|zmrolaV;rEU|Jv;>1UtYwQpbMiLKe&Fu#Cty?IuF!NI{kWxgCp z$>4Ak~R60#4mnb85T8K*J)+o^%l03+RC5@&aNSTw~$Qhyh&z zA1er%1SxVX7i?GcRZ`AY>Rwy`+WmP}s>aPqsqL7W8#hdm)-VkbQ`{H9JOhgLfmVe` zVEpqzV^w9PMP1loz{E2LN_T`grx%0rxE_3F0;R)RuSANhtfH~gCFv4;5v1^pw;`lc zR4NZ9#tBhcy1FNB{4!w(teLyfin9k(i{OD+6%Hw)iTFxSA%1n*n=vQv)hqDllNwTg z_h1&BO5oxd#qNUrR|xrx7y-o&oi2xB4FZ)9a49p>f8qwgMTRVX==!f-?#3Erzyvt2 zwB5^xWL6d4It55`L(LELKBFruTLm7^oZ8L@TW?{qGjNPX4tWK5n{xejhI5HYsMmEa zKe#A9f-+WAgr-oMm#1Bu0~;%1F09WTC_b?-5iwD27KsI>PDMmUT3cE^1KF}!x4mC_;QHUkBf|UHRX%m;o?#w5W4RdHDt$#NDM|u#2zGeLt%;42y!O z`+NqR$QcJz^Z^}Uz=Y2Z`uZ8u-*AjEFnriZ&8>HOAsv0<q|I`hdfK6p2NHXy>3cYyLH45mDntXv}sQEl3-^~E-Sn6tf|Ys z5O^MLZG3>&KpN!a(gb@T@LJ$m%$?b}sYU;U^KfF=d0-W6I( zf|@u!o_X)yy{O<|kG`toNBl(;;#hqcFvd&e)?oxS%)jK%>;nq{$S%-ymU zew(^|1`&XUk`fy}EqDIUAFyP5*IrT)^gi2O%mm|u8h?E*aijM2A$py^KSxZVExWlb zogDChzM_QX@ABjbdzzXm3~U2*jY2=t{)@%RGvBt|x6+Cs*WFmthU#wV?eC4fN;<(<@g z1g^iaHmC8nIqoq9htv=+KR@gce?Y%p-Qb1u9Z5esTkZKrFbF?8GQ+W_H@gzHo*K#k z#)Pl16$IX7GKt(lk91Mx?bOtguHzxN=85Z%DtNSg>2}WMrleTZKjuckk2A4Kl36DqkGkl;yJ>{E+2!0IqdxTCVyosvj8b!NfolgtZ5 z!^)2z{Ulej9zJX;-&hZ{9wJdvK>;Q$Ep1}LRB*q>f?3kTt-^Pkw%EZKI})FL^O78G zFdN)|2ZEa!x1J+>iAc*X-> zbbh>bzA+sk8pKL3-;2|K9<40PcZ-QF{`}!M1vI;d=YvRyqH@ilPVOclebe?=01OJ3&Lr>k*KtV zhK6EJo?QX>phje(Jtp8oLgAv8n4CVv(Gk4&+aYjHQYw~~u3 z1O}8efC3yuUn3zz5m>6XZrw`ubc-glaiRV4ueZN5EMT!jxhW_lbl8o;_10E`q21-n zufQ-Y4Eyv94Gplofbtu( zBhmI}uS?*`dh-UZ=2cLb9Wg*q{^Dg!*g&;0sJWS_^*%CL1Z<+(v3)XKz0RHWsy(Ay_-_*%4)EUC|F!q5*nJ z-o7nb2_hkw1BO8OJ_w?V4_ubG*V@;nrn6Jb2eEEl&khN_ae38pMW~BJrfdG@UM8#hK8L~R80*HPk)o#k$p^q2V*RB=v#reQl|zi2ijQf zR=7P@!+t}W4G#;Owxbgpf@+0;jW}xA3i~j&0&0_?pH#%f`h?O9bOE0)8_3Mspwygg zB)Kus(c8P^si?L*CrcE4zyUT9I%@}|BX*Lyn%XlmM(K}Q&1Wlf&yFV{#DD_T<22gXJ>GCmeB=z2GO~<_FF}36M}>_AD7hCLfO@zpXQJ0Osi>52& zHz1Q7zfO#Pk7b}fH%oX8l~YOLVL(t(R*kYt!9`R9O|!?b9P0n8#>%g6ZydYkdgaQ` zwKb1uW+Qia@QSYVd?qp@biq)+?`YIic2YEfmp@y{+ z22d!_J?;_ePL6tY34Ty{p~zD16TG{=P#1~qqK~R;^0Hx`rN2$$6WX%B3&uQG?IO@0 z2dGtI@(b|^Ai_9D2)0#!@({Yd?#r<-rTnM)Rd4|MxR>Gt&uXv~lgVV$__=y)v2 zMe$P=3N}d7J>7*F8MS?VrJV-Kr>{?qkEef);WcpnXYCNT|#e|;?fFq)V-P|hsFjm28;=r>d(T$_pSv*8<1!Pd3j=JNWxS= zCF8iZ8Kd&IIPUQ7?weM^e~KmVh$pQu4<+tsh94H@X@T!cG+U>T^@D5s9@&bKHG z?OyIN%h5-1ekcLw?BVcg1)H0l&F7A%5=2yRFF>)p-7DP!jg8;8Phk6sUjwbLaNp?M zIj&TJk!rLbX3l*Z8ag=n9j(gJGvC%FTxt2)(;hrt)5OD}MYXc33N2P*EL%NA*8vqz zm&umQLPJi-|B|W0x&BK7Fj#lLv^)ANPEoyw0>5o4aXm@dmksXj`T^1kdN@@R^Hrrs z5tz(*0zFxb`mWc8u;&z}!WMA*!WDoN-+{}D9z^Br;!St=wz&mZ@Mf3aAwoR9KQT#l4wj0ueQmG$#C!FmTiMdk&WUYoQXrb);mDkmR@dhj2PRJv za4IU(W2ElcRh(g&eW#8_e(G}G#?mm2Ehk7_m1XX^I9_vwyMTT{+1aV7dZwnwk}i3A zmcpFtxdC9P^Y-|I{rPe{fzB*)5^~@&OJh*PPy5kU!B;Wvm;d@T-?3w3E+w#~phl^v zNCvC%oTN4w<)+q{Iq2tuR{{|O_YfS~cHSR+$$UFY^$ADBnkF)Ztj9)LnB51G zeS8R)%S{!g;|`jOETf;LwjM1^c15#rQ;x4Dir;kkc#$@*p>RSlY;ix(%3vWDx6Q)%6M?CP5ejjC~hfvRR^ z-+&=cCOSGHuQj(!vMP#%bf>~qRrnBmCdKSf)xecBx$E~pxyCx_ z-qU2ElRIG-XRPiaK1nm!Pq(rvXj6Y-2L_RMnbpV(d^Si4okMR?6iA4R-|ag$Tf#{2 z;rOQhE<=Dx|De;La>Trmm)py8d>R_fP)5;nIynv{eO?T%oyPd>+(W16e|`plKd5Io zt?SqpDD!OPj6Q=f*-YWjTCHl4tKZdDWN>i!Vu$M^pxEkIe*^5ObgVrH%cdGgD0IZU zD=ifg6deD70T9K7$!SXLr}yu_K~k6pz{*BnEE|Od;49+fH7BR9fatQV+(C##v!<5- z&CpUaH#@7MpB?FHr0lNSyd_btN(NQgW02nt1h77)y#!tvH7X^0H zwjq&>4~s+CjtL2QZzdj;G>}@~)I{$kODt+lF)PrC%hA%|{^ihY*(%ag>mQ|;Xkcpb zt19!}SjT=K_VWEM-}q$l3ULX9!#+w4t(RR>5M>cH5{@L{0&}KuY-2c{u(&P25df+^ zw5neTr+Vb7md_-)5-q95Fk>y})vI&x4(P~J`w2lbU*Gp8A{HCHz(h~)@Y;RGxvhlR z6tuq~1EKYT#;+iyx`Uw(7_MAEPuQ zVvJ_tOi-9vS%C~n#}P_r)Iw_ZoId>)buf?B`k_g#$ByNHuOpF-2m5SDPob6F z+R>4fmX?;0aeQK;ZjMerwI#7fM^{%@M+fbZ&1T{)FW}L85*hjS%^P&*=yrhrDRHs_)WoPr*kkBM8r@i zG5jz9m~9DO%(d;V0l%qhkL2R=gOx3>1Xdlw>s05f$sc<}KWRO7}S63^1oRQQ=_M_|mwnScih zod}kvrAkRSKuqEWjq;p2^PgEl@8?@IBJAxFw~_b#Kc+m;%fJW8e-+)XoPUTi*AN|5 zU=DR|bHARRo(5kac+FKL_B;wz{+_Nb{}Zy0x9qyMrydBDSY^@!LBpt(o0Y{oGWf!@ zToT;pyLaO5yYC&BYJ*t<3N1|iRhWKalieuR0Mn<^+4}i2+Bl<8)6Q3h&=I?nuL3B! z+yt|X6{o+h>fcmIMPOrhYf<@#w|<~hoQ|vdUAFpYqIeG({~7MkuB%?-s7U_){R^iO zR!=<#QP^U|QfX&%k7JRStnAk2E1@`h7iuqpG4JW_hR|Am=lBC%)7p9j^8P~RQvn$w zj{R!1cTpv1Y3(Wqs~U7eM!$%Mwz+&c)Rtq`4CG&jF-Dr-u@n1{#i6Y;X95x=jP2* zo}zp*w4f+KFk6U8FW*yD@3stI16g?Y?p;(dvrMHWCDBcnbUM+_wC~jRwhvcD?sknp z{2A(cjx&j--|Tq8rn*2O3B@kd1o3C9l{yYS8?>pOzr%`;cBB4mT+ z*d`0t@^?OP-7^TfAdI;j;LIpT`u7MX{Kbo3z{}6}1jQw3bU4G7Ie3!T@ZmyLG$^3n`q1sNK9_1S70RrgKTx_5?~oWSO||3 zA*jhf85s2)h~BS-uKn@cvYT@s;8ROTYxA4J2+=1T9bK2-3}O^EL?p3U(wjfKg|{b= z^G7yF(J7!WDN7i<`Ayq4#bKp-q?NkM^dKualDffRx%nD`bF97-O4r)j+R=kUHB^_n zjo2F%Kyvc?z1xE?Q!1|=zPMY>3mO$D?ct#zxs|>-h=kg=#$mad@8{N8VzqwfGOEH} zbRMB(ddw8`B%t;cVp~*D`Z|<`{xVMp8@Hyu;#C2>D^&aWBUjN7mvFfq9bkAN#S;ie znwrzFEM%X1bw*Xy4!Ra`-MX$qtOTQhehB`|Ij5oO?Fm;BrM&xXQGaMA#6aF-nB_X- zKK+fPlT!eqn3ENXiUc>fD%iW+Myiqb&z64Nbx7gCYa*eg$x$qOjBvjyU`J&5)HU&C zh4PsNNX@etRIcEhsPpZ@@rfE?yc?A=C~_Jv1X^OfD`in;V>HD1hoy>9GSG zfUhEvtZHW!{%{d*x4@c-$7UN9s7%XX-`D0Cd3JvI@Ezh8vp5YC^%y7u)N-R;*I@`E zW}ZwUjs*KK*D;0Od9a?CmL7>7UuV%c)R-QNeK#PlbbNvr1$m&sdlG}dH2eX=XiZ#I zjy`c&8;W4q+21mW4Yz=J{sY&P4xL3is?6nmvmS6;a7uN!cA|u5-tJR1h?3X8`zLCZ z!+$56CvUF;AH9}R@)4tNbfFa`T^evfLS>7uX>F{^`{DqgQ2#G&D^$hOT?rx*? z6(l^INxMHuKrSfe(jAmFe*oWDH%1X(I0LWDqeMSo-ktp>rlwNpLTwm@SyLBmi1b;! zwS!p4-U=Yi$jx=M8(ZsJ1EVLnz_XRZyiM~ z9i3s;b2Nn6M!c$Jg)ZTwV?svk-1P^f1kFA6BBwbxI3y(##`uvJ7yrS@1=Lt+7U8KV z!@bs*$589BJ-`Oso^cAVoJkmbi9iL6@Yun_E0WOtyvZ54M52S$O|u;;v2dI zi`)Og>`TX3%HP(+Ue? zUUlF9-A?5qITC_^Y$utEnP_&1?$64QtKxnA)v+($3?uoDo5LF+{X~(RFoXAZg@wn2 zfnDVPpx#k@rIC?>kmN+P@&kGS=O$1)g5<=F#=ktXb&{w}M)Fw4I~HKK9~h7l6?Fss zoTL7UcPn1B1lpN15-)K=&TkT87AMrkLcG-atBXnkPz8@K-?yC@Iz*t91LciQe8WD= z$1~|==_lU_4|s3ImI&1i$^3{~)cZ^M(GRh_UO45tGk|2OPx#CQSO_W?F7#u$55LtA z5)y(#r0$o_2WS`&zlmz^5FBr^XUU7qz{AqBy9QD-F~Q3`Sen&$OS0o{&KZ>OPw zc?r*s*Ph^AR!x`S8G%a%Z)$#OZb!X9<{03`<>`NTWYaTR;6WgTDy>ZQSi>A2^wJ0PN*hh=gS@6UO%lt0H zF!Zw6ix?Xid;$BfmWVw`q{r_S?&bkDKCvZ(;>6PX4ZGiE!!cs3<+l^>O5CxRkvWu}XudSWDUDkp_fi|a6plJ6{3XcuF?)`Jwl;k|VY*}ooBwa$; z(`%t)lI6YTvSHyfH#Y`<#PJS$P=v-gzHlac4-Wa=6ivK(aA075K|!j>ZfSHmAtv8k zje}=d)O%grF;T}1Z$W`6G%+&rV}ECBYh7(ETF?%B%}-t;A>0-e7N(z`ZO1F0uotm` zA@9chgrb996o~Ag0H%EF0oUITaF7(V3~t?u>IB;qtzsYh;du34na>1bD99xEv_k;| zhOO&^os8zvxug!{Yd6{*gd|72Yhm~9-K00G5f6@p*IB$O?uIW2p>hN98KDA>k*_^H z&2gu6LMnVXkrB#Pf4v1sc=dc`EpiR&X}l=FRqTZgd7n03K^7j4#wd&5AcxWK-W-2A zvRjuR{RYqn1Y7NSMa7TM-rH?nlSr|@~|RYKi65K5sNRo(jy`zB{fg;fXQ{~ z{WlbiXYpbP;33NfoF&QS5xN~{aW{5$eg#(wkmfA|8JR)+IR04Q=VM&N%R$gWgAPn` z8Pt_jLb7r@FD(&h5T(`dwko_dqBIL#f2hKcn>F|EkZ!{rPMtmtd=+93XUbPd#B7NS zcSvv{@YW_KCK>87w4@cCN8ewd_|)7S{KInpT}?0?W2R5g27$B&P@=gk?fsDX^aA$o zhy#jVy!irl3hp3M0@TC7Y!3#06Vau5Kk1pR1mCgm-xaQrT7Z^9uTfc9S=?dT@H&9z zbl@AGNK2nGKxWjlV_>g~@4tay^$x`9kG(ruZV=r$FyxiQCM2LY)?(HrfWT&kw^uCx z`C?kvhk%B6yxr$)4l;Knu-PE{BEtagKV~{_WaJK~0`Wy5&38UN+qKKrlwn#A{U!17 zeaNSEPcW}!q@hE?=4mR1fMNv-2DxqV%v35din@# zHoS!`dF-t@$#L^L0~DGEIXJ3&dSd5>%-~G>T41;LUMPV>#>Au-$}lMYx+lQHaTsQi zVuidqiO&{^BK+S=)1 zrzj9YzR*+{SXjJJ{@=YzD#=W2W(JmNX>UI;GH3S5pY8u^?acpb-op03k;)u0b*NAY zr@?TFlm;PW$QT;Qa7c(IC8?aKBhfiBG?|m5K{O9SNMuZ*Qi%p>B%$GXe>Tte_51ufnKHlDvjX4_>&a{=s@}aOr82#^Ebe(PAQW58U>Gs%0vq-NFtt63;MNS`-$jG00 zmOU?37Di8;g;pD1DHsDmFT&(z(YmnSWa%|L$*|^igZ`4Tsah;C_~gxs+Yg|Z;#2)BPh9Wx@&Gf z`E-1?zUwx_Ha$Aa6j!@O$)Y5NodQqz_^sulvlEq-b4p6|G&GLbpLx2Og*@=)e0x>T z@51UttH1`#=FZ&YnUv=IdEZ(K-)q;Ju?}R{qX*4~M}-gPn(QemzvrN6#H+MG5m@T# zwi7$M&xqj{z`fx|w7E!sUeq|!YN^Z+ss-m=yWCL(Y&G^%5?T1%$2-1};G-u+~`d z!}mYp9w9QMhw*eh%Tzgqi{0;a6mnI4iC?FJDgxBH`(qWls-fOg5&9)zwv}b zK3>(1XGbdWi@!3>kTO|~vIJb_F49?}1ZGw(S`@hIao<5P4L#nl8PG5Qocr)Nf^Oae z2VF|N5NprrCq%$jnUtVeLlfk6Kd{JKS)X zfX@gCY1(hRgxm`=h@L}xc>7;9%Uu=sBe{7JQQ`IRn{$9 z6knU0$p__%l6uf{t;^eIsx@N7Nzj_aq@vbnZZTozON!>BW%B`xV zH@8usaRuj|*BK?+z*mrSz4$h(9cq7Mt47v|Vfyq<^mddPSiiIxK?V`M;)=Rex;Yj; zPFp$&@P`f_q$T4=(imG9^z7+Vm}`Px7VOo6Y(p6`WV(I`Euj&*cUZ5tvqR1^7@`D@ z2Pb?IZ`?o*^LfuSZ$;uAQ78Y3!ttsnDNjdO4Gxk(Pz{b!-LChPkVx}mj+2haFz>;G zQ`+0Dss`+YIs!Y!ENqc!Km@x7VR_n&8DBjdaRMYiZx?8Sc6Lifos^@Y%M23CAl>zz zkAf$j(2Zo4PAKs6yu4+VNh>vebccuBXVNnZIWm&@N zHC?daoX#jOMKGKOnB^_UZo#7B7LTf2bs>F>L(XD0Gve(`yZb@%i_Y+Swe5>!h7NsM zRAl00Wt+V&o?wOsbjF|0&dcAOhF)3d_(7tcwsYWs?!Ohiyi!(HCLf3w)1I1V%AO-b z7C$N3ze=REjEWg(>FKwCRcPG>KTKh#@DjB@LqeCQk;RPI-6`YZ=*UibR;R3MU~t7H z`Y(vOb8|2IwTy$11dRg_!A4@$V`>9t2i?t*+X2(@@_}LG@83K6wo#VZ1W?5FT!| zWJyq5m}`JX6XL*kRaJ!>=1w_{^b-nnE4%LK(9vp@EK%tx`Ha&e+J))GHI&5(O^3frj>RtLDzF;_eR3 zUpC9jD&G7*&}qkF6Ep)o;aLBF+XRA1prJg+xs9QJDVWeVQRX1$g;B*A{ z0Au5qUEJ-`stayQX&t@ZJE*_?#}%~3tK4g-_FsG`S8J*tG_WC}zfBNrGv?2e_XRys z-wV=VAULNvUYT3AL;LyR?6LvVh(|Qe_+qPr=1uh1>OX#bWBF?Rh7Ci84=(~$&*O~_4kU})qNlVTx-YBG=Kpr@SIdx1PP=tVpvR3X?%oPW zMHetJ&(?3M+@ssKdrWli{g-qmW}w=>;RYB|~XJqH-l|Vlz|}@?SIG%p0=%D=uYZ=&7nk<=toj@y07?|KioXxdf2D z^t|#F%o=#ZY^cjO$<7+16W7mV-IKLrB=x(CR?rnrw8{3a&y2rz<3`4wFB3Y~`DnT# zKc%0Zx;7B!0bMwBz7OQJY&ARu@@M_fqeba%Q@$TOAQ7C~PMwyfJ5YgaBr8k5^I(hb z@V@pvj#WFKKIq^mI&SnF`JhGDq5C~0 zWgJ(pj(gti(f@J*R$F^C&33W=^J$HM(9!ZMn_(>TH<<&ps+IHRT~5=kq@G1{b2)Ij z>Mis3IP?Ed?Sic4Yoz-5NoB5W_5i-dSGBaKm^3bs71Xi=&1wZ&H@Ult{)Y3{`_a`w1sFJ_K%crOdCMR z3AX2|VI{Y233Qj`mwYlw)P*=(72cb8MoqjlY>}(2&FMRXn&pR#J|d+kzh>=Pw8k&r zua?Pu_^=KrjGSn>U(cOOR;?O_fjHh7-vZQ*fxSmWL`>W3re>To0I4r-@abOHFrqUs z5Y4onZDwTT4WF~B%LJm}pi5n|ef;)sdoubz%Zay6_BKd|=eYe%;?=aR0fQwBFFi-Z zx;RWnd1Huik8F(L`}XT+3AqhUy-UL+HczO)|vy^llI2ak!vG28YH9I2lapbl&gFa9Yc@rbgbDGMFahu5E2}Lcg?67b>HEziC;dIbX#ez4pGrh~_(d z(AP!>azRID=l;EWBYnT5bIohX>UIuhK&!N?qd#dhx#I%c31wGMx6>qzu}(#4LfR4) zc-MV+k))4OTm7)zZ6axXmEdo5XVgHhvu!@N=due{e)!-_gXeF>AQ`R%8w9I_jfdHW z9yjzu;6jm)d)mIX#{IP~yyvWLYN>uY7EVXZTY)0hv@NMF-R3ikHQ5gh^k4?r8#Jv zJW!y<`0;0Srft~F%*yEWD^Fpf$E>;GpKEtat?qFl`>^!PzDp|D_~GyXsfHddEiDCL z@B`{waanRKw*VlW0uSX=Ro6;tXz~um2=v7>q%fg-*|QffKEpVslugda2ummd#UuMy znBn|ikiNdCaRtpR3K7r*M)fof@*g`WB1d&%Sz;pUwLb|>(>osU-YY7|M!?tiWM;9- zA?TB*mlPN8F`vD}NIJExrnIg`BF}8d0P%e$2RS!GeJi`S6R=oDec@d`LG!LgwM%5O`$VnJ={KXL`1uuxy0r z{pGzxDMW{Y0w-(7wTpFy%#0Px+hbBaP{LWpwPU8YV0e5qdcXGwHVf}PGM0d<# zFOkHuT{CB_&CQEK{O;%F!KK78DhKS2M^RC7;p{zL`#?9scY-@r=bc-=Vg=gmP|6_- z3oxMD4MAs3cH}IEvcn#Pe|GLGYRz3#U>*sosGBN-Z?;j_HAOxK{eR|o6=qYSF zqqBoEz9na*ZKQ1XTy|FRmFZ=*V`DUQumi;%(RrvSs8B{qxTnYNze5ug??Bl`0Q8b*lEm zhr834uC}!7Af+L-zMwf||Nd=?|4Bao)2F|J=ukmvX?SR8yD+jx9TOJP#Xtdsl?y$-MkmD(SFe1Vd}Y{F5k`iDTVMftCTu188r3TGS^cIWIN zQ@m9@SqvK=hj(C{du{gW)!*Q_A)Bc9ddAQf3OE#n^gUnv?QJ!OqvZd`RPy#sEty_D zsxu7z28e>FzL@oN4F3UO06u-Y%ZTufLHbE1?THhA)3Aey%Rm#xJ?2kLg)R;wj8v63 zLS@I6@+e|HS`u%oAf+V6$J-9mWz|RNO8wQ4vlzb_c3Ny_a)+|L0(lm_de!tLS7L{J-Zsi9;V0me(7x@}j!W{p$aEEic>SqMab+SwU*&H$%H z+B{FypDO{ACl@43IE^rm)(+30KKE*L!q|k(L8I5MO&GUsgq&QnR-9eM_9jGc0DS^r zbqzD~abw2ZLN~Ebs^?KMjB0e6I2|PtvO5SPD0tpIA2=zl-yMV4j_JY$dAb2P14%;o zLHK)$DSP^K-nw|n7J#X1Aih+(uq$B(ATxgg?8Jj0$ZdY{LbkJy<@KZ_E{>Rc1|u%c zAOYxLm1q#qkiJ1z1;cneYxZ{|I5M|xdF$m;vOK`{w{XE%gMCf$ZSb?Pf=R|uSU8t} z9p}xrF?&RzOnj%tR~Uk^e?vH70f_ zM}fj{E3s^$W@~Jfc``yFfZkpN3-?$WfGDma!g(qY{iQ0-r=+|BI;1UbkMA}zONDlk zu>PBd4jU$*#&vad^7ZE;BO7s5wCCuHQ8PuFHYCHLQ_RVwxopO4{NGB-$`_)eU%wZA zo~g>Rn{Ly{7O4jyq@4zAOE?eDVveoSp`6%?dl=t93#e50$;Jk-la|Q0oxjU0AU(i~ z1_)-~{h?r#Aby>m*|ThHels~y|DiPw=vmY_j{(8o!~J+4_tXUr4)vfZ3+B%!4n{2+ zH;pX@$pM}Vm7zcEaN_YAJiJUQQ&t}xpI}m56_cLsv3vJ*ADaWE@9kb;pm#g#HC^J`=)j+ zpko=DbH}RC(AwI%ZJfruX{E#T$$~JTiT>}u_AaT&r|K5TaTt4)%J)<GvjI+(Vy6#4V4r$>|a@(7`z+W~#zHa;YrY+=g{LwH+vzvU9fz{PbMM}vW zVVC2T(A3{$7414)lyF2i3+d|BN9wNpf8&s2ChvAO-L{(yeu(?CVPf6etS*i|N7{-OnDf5T~Cp}E70sq-8yLG~{ZKS77UlMpP=dm!95&Dbk)z>E0k^Ja-cm|om zoPQ@864dKvW54Z_eW3c>*RF|xNXWQ7--((~P%E)*)ZD;^wB!Mg28iT7N7JSjs6KDVnmvX;fbk#U?e7kIY z;HsQy?$#~xc?}}|sd9%i)|#1>H#98XrX;*l#?zkGYHZG|6%nWN>ENi_y%4=%aMjn)I)Eo}@>H0&sl?DSOt=a+6;bI&c z&;{p3ko}bQ^vPtxuSwXrkoChyCMIGVFsbS)tsjCOYkqmoI{~!?L4f+*T2GFOl1+XK zEnvYJ^|!V-?S1?9U28_*+}PAqZl+Z2hX)o$@vP^4*zOU@NV5Pe-lrEYbacE%!Fr(A zw@sAn!kn$A#~{SFhhj5sBL}aX#k_jQ4$YJ_x0a2j+QZU8(nu6D;rG-Rr|7pg`k=@% zlmV&cT#?=1yE-ptqS_n3f^NsL}cZH5%C9uuNv!^IKDcV$*U1P25-LO5~7K2ZE({KB0i z%7vrB98b5Xi4VFlkXzm~1;u3eU;8r&%V%}GckFa_R!IUkwgMfq6(3O`v#4XD=Lyq| z2(eT0-0t@B#%auyPg;i%I`i&CLmA>PG3TGVKkw0ttO|_74_Mfl&YxdVqZW6`3Nl{>Rq!FV)Jv~gWF4V=Rk13aLE zhtK}~-3k{Ha^F$44exswz9XfskmS;c9X0Axd3m1K)Cc zp&`h2=QilCD^-^ovW%NHZrO6`=+W#_nu8Ch&Y~Xu3^NxL^z;ccq2peW0l%9iUrr&F zQ*aIW2GK@+)m}JFH3X()Ifi$Y=YbyHiqhV@dSy}%{~AY`+PO`f{blMv0>Pts^pVEe z_Lh1MGi;f>^*pJ^BTgGkP^RdCNvBcnrFgJQ&66;zYKk+lNMsbHkh2*2atbMCuAipS zLW1^{3oUY6E!c|g6*Pme%g^bq&UResOlELkp716E=`ZKn{=~;M35I-|%$#C6*MV|> z_$Md>07q*cV@e+_{@{@&{sx(j37*q5PUX5C@1g3!f62p*Q@bI7V6UO*W=aMLX1j)b?Mg z>@~<=Y^GkFEecS`-w=C7ih3h7P1t3Gw{2e_D?ab&<^_eE$6%7VpGd*-zYTdZDrUmb ztsOne)bjhBcFeRCugrsCwWbPQkCpknaONKNsD zNT2bP)#vias;4cUdS(VQxH9pde_qhxQtdmob=uot3Y<&-=e2jboI4?LHS7F6T(F-` z;iNGSs)XLR4<=FR2qopP9I+|-jvDKx+inG?@Cs!C%%U!;OvJX~z`Q&1o5C(fMrv+( zq53P7%CP*_<5uIaD}1X_2!1BHtNtWcBz3YZ#rC2Rq!cE`!6Qc+@}4_q-V#*BitGG) z>|i|+-E_>qLpk}N`_H@ml7o) z?bK6R+fE@wjJ*e*_hAcVP0cK;N%vN_?^szQ+((f;d%@)*Slb_?4Cd0dzi`RgS_~K@aTPMQ$CGf@2wxk-0?5B=0mQ+GK>@L!Kkv@JQ3&tY@c--((%vWj*g7;tt-Pujlu$TH zlb?ZO3O+cT;o%3^02>9yW=d)*;(vln7=ZS@z)^a-x%eU_ui2Aqu#nnPBdgu9y=`Yq zE2;*e!I)T{^_49V+GuU|`1{17qVm5S5DFP@ho~7e0AXHcQjixc|5H zTOAz0fq$T)cwJhW@3dGaY$o{!`O(<1=fWeVz&_=WpvwBQvjcQo>SQFy(%eAzz*WK{ z7UD9SZDWz?!C5n}^xiIeh&Opaou3748E(ntUy&>7tvL0iY;qea51YsKw&YBS!E-Ef z2K=}{>B_Nd&1C8mS%%A(gMp7TJrT#zWBHakB`I{8utk|Q%LldrtcgP#9(=!Y{rYli z>xkbCVL`xddNrfz>0AXp?9d7?`z{a38L*_D11+G`*>0!fM{|9G zs_K$o*~pTtDx7)asc{^IVTYxYp4a2ac4W@uQa;t!2R;z*7pYT&DqyirC!Md`HZ;Hq z&yMgp-K+hu{KXT?F=SVF@!=(+OZ#Q@*^0qbE9>F55FuQL^@>!$#CDh?%Fnl$o!!zD z=C0yH$)&>gk}f)S=e)06Qad+ZiZ@9#?qs*Zthh~3SR5}`bhKt{YY$&zmdzO-yb`FNrM??9pCAYS3=ea2@LH2s}8u| zFTHK2iwiuUaW2@1-Ch^(I&hu|`QeTmfQ4qqB#Hv%_10KgJ}SNVyhgB!xbd?n5#D#^ zc@2%XQ7N2FdpD&bPUw1mywOvFQ;Q$IeH&4X7(AS_xqf|78*dmbeGAM6$fcNm=GE9( zh22V{bEe0Kqy6zbr__s)Am1UEY!#v#?Xq8c-mS%3z@2({Y95~Rys&WGmF}&%)vz_( zj+vTpjRd!L;w@Cha=Ah}jhtmX0{{$0&d`7hQBfu_SZg8Hs=#ns&mWckXnj|A5&+ z-|59g@qSgV9c8=S9t{7V;NbP!8Ohi+H==3!HZGp1r1QP+zej91UcgsKZUxQfgrA#8 zfMGxP_1IgWMgvya)BuzKjs|$tPfN~V91R})4e<5+&E17m4`^OW-Cmr0?#=eG-7aBB zFO*W~LuF;03k5Ejr^CjLT5X#o70JhO)>Khej(4fq{hfV*L^^7rIGUaHmbzWa@f1s! zrgDBK947aWT)RE)?%G;f7~ym)!k=>X%9#>|9$yMpMR^F5DYC)!dCToY!Y4JuQK8&M zCOSDbe58^Eh_iRkKKGLZ!%mo5Z0ojtg z$bZHA*5_dw0XRbeVejH}uIAU%OjUN_lthA-uGiZnkTQi*T4*@gGmN=lv;v!!#~A;6 z0#}L)?h+*0C19EyGtG0jg0xaL1OaZt?0Sm22tD`Xw|*|DR99;j)J`}q+*(I%&e!8i z0nP$dxYvDBD@sy^vLP3pK6gDwcyFc&E;~m&)0=L_PS+1T z797kj#$nO36S;rm$BaSu6!6whav-dmCc4y^rTHc_;iDl4YgZf<#@!%P`Yfxzg53Zd zuiT0KFe`p|ptOl!rqzdRQ$0!Bo%GwQ*8H6xY z2nTQ*U*TKk45UnJsMbh4wyuMU(7ttQ3PsMgP3qyArQkZmVc$?EBWdAx1f!f##bLJM@f@lF*nj;|&DrE6wo<3GPg& zU)MUgw?7ME^VHXPLhi;OQPRgy3!)i@59({KAKYbTFQX5Y_5`}CrAr5GddF$IoPKzu z;Ia5p_o)tVy*qyF*xLZF`|i_Fr;xFIS&0cXjhM3(OVY?xc09mM=uq> z)i?5DmETn7y4WM9&x%A+ZS#x`mlqKOcZ9WJc*rjG9ryf#0<$4~UF#v{3J`y^2fCga zS;E^zqPG1N;R?@)4Aig`R=KY@9Kr?5bDG^t|LyHMMqB$U-gQ`%S8lP6UpE_9FYt2Z zpEKeaZSYw##)gL3)K55zq`VfCPw-0_stHEfk+i!(dI2^e_#H|>F;K<+a(ae~`igAf zs|~uF>DC<%=41wXl$^Rj7kK&`-b$j!4hWcUvO;UP7i2|Fu-gj?WbyA2TJ0S2`*X-; zG)LEd8%@;RR-8O(!UX>-dyC?15#+!ex%m7*)JC6tx)xtJ|42B^45+E{+*W7v&~bprFtaNG9e8U)Bw45jwMrBO%$%N z=JDOL6ot`?43(DEw`c8goG544ZmBwrT?eECiV{eQ%565sekbj~^^MFMjKe~kAoz*A z15}?L#y@uAs8u#*vJi)VA3AaB)ZOIypq63V3!Xn;o8{R-#zOib5wY+rXcD1-K3`>}Xfo=kZ<(X$Bd2RaI5kd!xR={~pwO zUhne7f^#&dPQ9LYMUAbR)6QRG5r&_CqxghY(RZWe0Sa2Ag{;D#j#*A_QuJGx(Ig$u za&vo4@s?DaGNpwxqXYpV#a4*R6GEogWpA)gwv7E$;U{@@4*XQ%_nAtFraNDGrp0@` zJ>@h|$`=|cOylTCEB0Hqh!&P7Z!amihw(OW0Oz&bJSP41lp+KdsKY%!3)g3G{?M+bStJxG=qcGo($eQl7zf0}bpm1#!0C|zGiNKw zdVzkyjzCMPq@qIqoY>aTbsWOa}D4 z57x!+$;jfUq<_XQ;}~p!^*?QGN3XfDgsW`c$K;3C1Gnbu_b33NusZNBqb$m%Hm@_>-@Mdg$YlXLr=h? zufj|kH#-Pfj0IQ5LpL^nI&=Q~`LJpmsd544Sw%c^6as&MsQLNhWp)@OsqFisr%wqJ zkNT~7dzx+^%C$qOGZk+;y-648p=myzbLsgjM;_J0`y3)jnGdMM-)lLa`__ (AST), while at the `data-flow level` it is +represented as a `data-flow graph `__ (DFG). In +between, there is also an intermediate representation of the program as a control-flow graph (CFG), +though this representation is rarely useful on its own and mostly used to construct the higher-level +DFG representation. + +The AST representation captures the syntactic structure of the program. You can use it to reason +about syntactic properties such as the nesting of statements within each other, but also about the +types of expressions and which variable a name refers to. + +The DFG, on the other hand, provides an approximation of how data flows through variables and +operations at runtime. It is used, for example, by the security queries to model the way +user-controlled input can propagate through the program. Additionally, the DFG contains information +about which function may be invoked by a given call (taking virtual dispatch through interfaces into +account), as well as control-flow information about the order in which different operations may be +executed at runtime. + +As a rule of thumb, you normally want to use the AST only for superficial syntactic queries. Any +analysis involving deeper semantic properties of the program should be done on the DFG. + +The rest of this tutorial briefly summarizes the most important classes and predicates provided by +this library, including references to the `detailed API documentation +`__ where applicable. We start by giving an overview of the AST +representation, followed by an explanation of names and entities, which are used to represent +name-binding information, and of types and type information. Then we move on to control flow and the +data-flow graph, and finally the call graph and a few advanced topics. + +Abstract syntax +--------------- + +The AST presents the program as a hierarchical structure of nodes, each of which corresponds to a +syntactic element of the program source text. For example, there is an AST node for each expression +and each statement in the program. These AST nodes are arranged into a parent-child relationship +reflecting the nesting of syntactic elements and the order in which inner elements appear in +enclosing ones. + +For example, this is the AST for the expression ``(x + y) * z``: + +|ast| + +It is composed of six AST nodes, representing ``x``, ``y``, ``x + y``, ``(x + y)``, ``z`` and the +entire expression ``(x + y) * z``, respectively. The AST nodes representing ``x`` and ``y`` are +children of the AST node representing ``x + y``, ``x`` being the zeroth child and ``y`` being the +first child, reflecting their order in the program text. Similarly, ``x + y`` is the only child of +``(x + y)``, which is the zeroth child of ``(x + y) * z``, whose first child is ``z``. + +All AST nodes belong to class `AstNode +`__, which defines generic +tree traversal predicates: + +- ``getChild(i)``: returns the ``i``\ th child of this AST node. +- ``getAChild()``: returns any child of this AST node. +- ``getParent()``: returns the parent node of this AST node, if any. + +These predicates should only be used to perform generic AST traversal. To access children of +specific AST node types, the specialized predicates introduced below should be used instead. In +particular, queries should not rely on the numeric indices of child nodes relative to their parent +nodes: these are considered an implementation detail that may change between versions of the +library. + +The predicate ``toString()`` in class ``AstNode`` nodes gives a short description of the AST node, +usually just indicating what kind of node it is. The ``toString()`` predicate does `not` provide +access to the source text corresponding to an AST node. The source text is not stored in the +dataset, and hence is not directly accessible to CodeQL queries. + +The predicate ``getLocation()`` in class ``AstNode`` returns a `Location +`__ entity +describing the source location of the program element represented by the AST node. You can use its +member predicates ``getFile()``, ``getStartLine()``, ``getStartColumn``, ``getEndLine()``, and +``getEndColumn()`` to obtain information about its file, start line and column, and end line and +column. + +The most important subclasses of `AstNode +`__ are `Stmt +`__ and `Expr +`__, which represent +statements and expressions, respectively. This section briefly discusses some of their more +important subclasses and predicates. For a full reference of all the subclasses of `Stmt +`__ and `Expr +`__ and their API, see +`Stmt.qll `__ and `Expr.qll +`__. + +Statements +~~~~~~~~~~ + +- ``ExprStmt``: an expression statement; use ``getExpr()`` to access the expression itself +- ``Assignment``: an assignment statement; use ``getLhs(i)`` to access the ``i``\ th left-hand side + and ``getRhs(i)`` to access the ``i``\ th right-hand side; if there is only a single left-hand side + you can use ``getLhs()`` instead, and similar for the right-hand side + + - ``SimpleAssignStmt``: an assignment statement that does not involve a compound operator + + - ``AssignStmt``: a plain assignment statement of the form ``lhs = rhs`` + - ``DefineStmt``: a short-hand variable declaration of the form ``lhs := rhs`` + + - ``CompoundAssignStmt``: an assignment statement with a compound operator, such as ``lhs += rhs`` + +- ``IncStmt``, ``DecStmt``: an increment statement or a decrement statement, respectively; use + ``getOperand()`` to access the expression being incremented or decremented +- ``BlockStmt``: a block of statements between curly braces; use ``getStmt(i)`` to access the + ``i``\ th statement in a block +- ``IfStmt``: an ``if`` statement; use ``getInit()``, ``getCond()``, ``getThen()``, and + ``getElse()`` to access the (optional) init statement, the condition being checked, the "then" + branch to evaluate if the condition is true, and the (optional) "else" branch to evaluate + otherwise, respectively +- ``LoopStmt``: a loop; use ``getBody()`` to access its body + + - ``ForStmt``: a ``for`` statement; use ``getInit()``, ``getCond()``, and ``getPost()`` to access + the init statement, loop condition, and post statement, respectively, all of which are optional + + - ``RangeStmt``: a ``range`` statement; use ``getDomain()`` to access the iteration domain, and + ``getKey()`` and ``getValue()`` to access the expressions to which successive keys and values + are assigned, if any + +- ``GoStmt``: a ``go`` statement; use ``getCall()`` to access the call expression that is evaluated + in the new goroutine +- ``DeferStmt``: a ``defer`` statement; use ``getCall()`` to access the call expression being + deferred +- ``SendStmt``: a send statement; use ``getChannel()`` and ``getValue()`` to access the channel and + the value being sent over the channel, respectively +- ``ReturnStmt``: a ``return`` statement; use ``getExpr(i)`` to access the ``i``\ th returned + expression; if there is only a single returned expression you can use ``getExpr()`` instead +- ``BranchStmt``: a statement that interrupts structured control flow; use ``getLabel()`` to get the + optional target label + + - ``BreakStmt``: a ``break`` statement + - ``ContinueStmt``: a ``continue`` statement + - ``FallthroughStmt``: a ``fallthrough`` statement at the end of a switch case + - ``GotoStmt``: a ``goto`` statement + +- ``DeclStmt``: a declaration statement, use ``getDecl()`` to access the declaration in this + statement; note that one rarely needs to deal with declaration statements directly, since + reasoning about the entities they declare is usually easier +- ``SwitchStmt``: a ``switch`` statement; use ``getInit()`` to access the (optional) init statement, + and ``getCase(i)`` to access the ``i``\ th ``case`` or ``default`` clause + + - ``ExpressionSwitchStmt``: a ``switch`` statement examining the value of an expression + - ``TypeSwitchStmt``: a ``switch`` statement examining the type of an expression + +- ``CaseClause``: a ``case`` or ``default`` clause in a ``switch`` statement; use ``getExpr(i)`` to + access the ``i``\ th expression, and ``getStmt(i)`` to access the ``i``\ th statement in the body + of this clause +- ``SelectStmt``: a ``select`` statement; use ``getCommClause(i)`` to access the ``i``\ th ``case`` + or ``default`` clause +- ``CommClause``: a ``case`` or ``default`` clause in a ``select`` statement; use ``getComm()`` to + access the send/receive statement of this clause (not defined for ``default`` clauses), and + ``getStmt(i)`` to access the ``i``\ th statement in the body of this clause +- ``RecvStmt``: a receive statement in a ``case`` clause of a ``select`` statement; use + ``getLhs(i)`` to access the ``i``\ th left-hand side of this statement, and ``getExpr()`` to + access the underlying receive expression + +Expressions +~~~~~~~~~~~ + +Class ``Expression`` has a predicate ``isConst()`` that holds if the expression is a compile-time +constant. For such constant expressions, ``getNumericValue()`` and ``getStringValue()`` can be used +to determine their numeric value and string value, respectively. Note that these predicates are not +defined for expressions whose value cannot be determined at compile time. Also note that the result +type of ``getNumericValue()`` is the QL type ``float``. If an expression has a numeric value that +cannot be represented as a QL ``float``, this predicate is also not defined. In such cases, you can +use ``getExactValue()`` to obtain a string representation of the value of the constant. + +- ``Ident``: an identifier; use ``getName()`` to access its name +- ``SelectorExpr``: a selector of the form ``base.sel``; use ``getBase()`` to access the part before + the dot, and ``getSelector()`` for the identifier after the dot +- ``BasicLit``: a literal of a basic type; subclasses ``IntLit``, ``FloatLit``, ``ImagLit``, + ``RuneLit``, and ``StringLit`` represent various specific kinds of literals +- ``FuncLit``: a function literal; use ``getBody()`` to access the body of the function +- ``CompositeLit``: a composite literal; use ``getKey(i)`` and ``getValue(i)`` to access the + ``i``\ th key and the ``i``\ th value, respectively +- ``ParenExpr``: a parenthesized expression; use ``getExpr()`` to access the expression between the + parentheses +- ``IndexExpr``: an index expression ``base[idx]``; use ``getBase()`` and ``getIndex()`` to access + ``base`` and ``idx``, respectively +- ``SliceExpr``: a slice expression ``base[lo:hi:max]``; use ``getBase()``, ``getLow()``, + ``getHigh()``, and ``getMax()`` to access ``base``, ``lo``, ``hi``, and ``max``, respectively; + note that ``lo``, ``hi``, and ``max`` can be omitted, in which case the corresponding predicates are not defined +- ``ConversionExpr``: a conversion expression ``T(e)``; use ``getTypeExpr()`` and ``getOperand()`` + to access ``T`` and ``e``, respectively +- ``TypeAssertExpr``: a type assertion ``e.(T)``; use ``getExpr()`` and ``getTypeExpr()`` to access + ``e`` and ``T``, respectively +- ``CallExpr``: a call expression ``callee(arg0, ..., argn)``; use ``getCalleeExpr()`` to access + ``callee``, and ``getArg(i)`` to access the ``i``\ th argument +- ``StarExpr``: a star expression, which may be either a pointer-type expression or a + pointer-dereference expression, depending on context; use ``getBase()`` to access the operand of + the star +- ``TypeExpr``: an expression that denotes a type +- ``OperatorExpr``: an expression with a unary or binary operator; use ``getOperator()`` to access + the operator + + - ``UnaryExpr``: an expression with a unary operator; use ``getAnOperand()`` to access the operand + of the operator + - ``BinaryExpr``: an expression with a binary operator; use ``getLeftOperand()`` and + ``getRightOperand()`` to access the left and the right operand, respectively + + - ``ComparisonExpr``: a binary expression that performs a comparison, including both equality + tests and relational comparisons + + - ``EqualityTestExpr``: an equality test, that is, either ``==`` or ``!=``; the predicate + ``getPolarity()`` has result ``true`` for the former and ``false`` for the latter + - ``RelationalComparisonExpr``: a relational comparison; use ``getLesserOperand()`` and + ``getGreaterOperand()`` to access the lesser and greater operand of the comparison, + respectively; ``isStrict()`` holds if this is a strict comparison using ``<`` or ``>``, + as opposed to ``<=`` or ``>=`` + +Names +~~~~~ + +While ``Ident`` and ``SelectorExpr`` are very useful classes, they are often too general: ``Ident`` +covers all identifiers in a program, including both identifiers appearing in a declaration as well +as references, and does not distinguish between names referring to packages, types, variables, +constants, functions, or statement labels. Similarly, a ``SelectorExpr`` might refer to a package, a +type, a function, or a method. + +Class ``Name`` and its subclasses provide a more fine-grained mapping of this space, organized along +the two axes of structure and namespace. In terms of structure, a name can be a ``SimpleName``, +meaning that it is a simple identifier (and hence an ``Ident``), or it can be a ``QualifiedName``, +meaning that it is a qualified identifier (and hence a ``SelectorExpr``). In terms of namespacing, a +``Name`` can be a ``PackageName``, ``TypeName``, ``ValueName``, or ``LabelName``. A ``ValueName``, +in turn, can be either a ``ConstantName``, a ``VariableName``, or a ``FunctionName``, depending on +what sort of entity the name refers to. + +A related abstraction is provided by class ``ReferenceExpr``: a reference expression is an +expression that refers to a variable, a constant, a function, a field, or an element of an array or +a slice. Use predicates ``isLvalue()`` and ``isRvalue()`` to determine whether a reference +expression appears in a syntactic context where it is assigned to or read from, respectively. + +Finally, ``ValueExpr`` generalizes ``ReferenceExpr`` to include all other kinds of expressions that +can be evaluated to a value (as opposed to expressions that refer to a package, a type, or a +statement label). + +Functions +~~~~~~~~~ + +At the syntactic level, functions appear in two forms: in function declarations (represented by +class ``FuncDecl``) and as function literals (represented by class ``FuncLit``). Since it is often +convenient to reason about functions of either kind, these two classes share a common superclass +``FuncDef``, which defines a few useful member predicates: + + - ``getBody()`` provides access to the function body + - ``getName()`` gets the function name; it is undefined for function literals, which do not have a + name + - ``getParameter(i)`` gets the ``i``\ th parameter of the function + - ``getResultVar(i)`` gets the ``i``\ th result variable of the function; if there is only + one result, ``getResultVar()`` can be used to access it + - ``getACall()`` gets a data-flow node (see below) representing a call to this function + +Entities and name binding +------------------------- + +Not all elements of a code base can be represented as AST nodes. For example, functions defined in +the standard library or in a dependency do not have a source-level definition within the source code +of the program itself, and built-in functions like ``len`` do not have a definition at all. Hence +functions cannot simplify be identified with their definition, and similarly for variables, types, +and so on. + +To smooth over this difference and provide a unified view of functions no matter where they are +defined, the Go library introduces the concept of an `entity`. An entity is a named program element, +that is, a package, a type, a constant, a variable, a field, a function, or a label. All entities +belong to class ``Entity``, which defines a few useful predicates: + + - ``getName()`` gets the name of the entity + - ``hasQualifiedName(pkg, n)`` holds if this entity is declared in package ``pkg`` and has name + ``n``; this predicate is only defined for types, functions, and package-level variables and + constants (but not for methods or local variables) + - ``getDeclaration()`` connects an entity to its declaring identifier, if any + - ``getAReference()`` gets a ``Name`` that refers to this entity + +Conversely, class ``Name`` defines a predicate ``getTarget()`` that gets the entity to which the +name refers. + +Class ``Entity`` has several subclasses representing specific kinds of entities: ``PackageEntity`` +for packages; ``TypeEntity`` for types; ``ValueEntity`` for constants (``Constant``), variables +(``Variable``), and functions (``Function``); and ``Label`` for statement labels. + +Class ``Variable``, in turn, has a few subclasses representing specific kinds of variables: a +``LocalVariable`` is a variable declared in a local scope, that is, not at package level; +``ReceiverVariable``, ``Parameter`` and ``ResultVariable`` describe receivers, parameters and +results, respectively, and define a predicate ``getFunction()`` to access the corresponding +function. Finally, class ``Field`` represents struct fields, and provides a member predicate +``hasQualifiedName(pkg, tp, f)`` that holds if this field has name ``f`` and belongs to type ``tp`` +in package ``pkg``. (Note that due to embedding the same field can belong to multiple types.) + +Class ``Function`` has a subclass ``Method`` representing methods (including both interface methods +and methods defined on a named type). Similar to ``Field``, ``Method`` provides a member predicate +``hasQualifiedName(pkg, tp, m)`` that holds if this method has name ``m`` and belongs to type ``tp`` +in package ``pkg``. Predicate ``implements(m2)`` holds if this method implements method ``m2``, that +is, it has the same name and signature as ``m2`` and it belongs to a type that implements the +interface to which ``m2`` belongs. For any function, ``getACall()`` provides access to call sites +that may call this function, possibly through virtual dispatch. + +Finally, module ``Builtin`` provides a convenient way of looking up the entities corresponding to +built-in functions and types. For example, ``Builtin::len()`` is the entity representing the +built-in function ``len``, ``Builtin::bool()`` is the ``bool`` type, and ``Builtin::nil()`` is the +value ``nil``. + +Type information +---------------- + +Types are represented by class ``Type`` and its subclasses, such as ``BoolType`` for the built-in +type ``bool``; ``NumericType`` for the various numeric types including ``IntType``, ``Uint8Type``, +``Float64Type`` and others; ``StringType`` for the type ``string``; ``NamedType``, ``ArrayType``, +``SliceType``, ``StructType``, ``InterfaceType``, ``PointerType``, ``MapType``, ``ChanType`` for +named types, arrays, slices, structs, interfaces, pointers, maps, and channels, respectively. +Finally, ``SignatureType`` represents function types. + +Note that the type ``BoolType`` is distinct from the entity ``Builtin::bool()``: the latter views +``bool`` as a declared entity, the former as a type. You can, however, map from types to their +corresponding entity (if any) using the predicate ``getEntity()``. + +Class ``Expr`` and class ``Entity`` both define a predicate ``getType()`` to determine the type of +an expression or entity. If the type of an expression or entity cannot be determined (for example +because some dependency could not be found during extraction), it will be associated with an invalid +type of class ``InvalidType``. + +Control flow +------------ + +Most CodeQL query writers will rarely use the control-flow representation of a program directly, but +it is nevertheless useful to understand how it works. + +Unlike the abstract syntax tree, which views the program as a hierarchy of AST nodes, the +control-flow graph views it as a collection of `control-flow nodes`, each representing a single +operation performed at runtime. These nodes are connected to each other by (directed) edges +representing the order in which operations are performed. + +For example, consider the following code snippet: + +.. code-block:: go + + x := 0 + if p != nil { + x = p.f + } + return x + +In the AST, this is represented as an ``IfStmt`` and a ``ReturnStmt``, with the former having an +``NeqExpr`` and a ``BlockStmt`` as its children, and so on. This provides a very detailed picture of +the syntactic structure of the code, but it does not immediately help us reason about the order +in which the various operations such as the comparison and the assignment are performed. + +In the CFG, there are nodes corresponding to ``x := 0``, ``p != nil``, ``x = p.f``, and ``return +x``, as well as a few others. The edges between these nodes model the possible execution orders of +these statements and expressions, and look as follows (simplified somewhat for presentational +purposes): + +|cfg| + +For example, the edge from ``p != nil`` to ``x = p.f`` models the case where the comparison +evaluates to ``true`` and the "then" branch is evaluated, while the edge from ``p != nil`` to +``return x`` models the case where the comparison evaluates to ``false`` and the "then" branch is +skipped. + +Note, in particular, that a CFG node can have multiple outgoing edges (like from ``p != nil``) as +well as multiple incoming edges (like into ``return x``) to represent control-flow branching at +runtime. + +Also note that only AST nodes that perform some kind of operation on values have a corresponding CFG +node. This includes expressions (such as the comparison ``p != nil``), assignment statements (such +as ``x = p.f``) and return statements (such as ``return x``), but not statements that serve a purely +syntactic purpose (such as block statements) and statements whose semantics is already reflected by +the CFG edges (such as ``if`` statements). + +It is important to point out that the control-flow graph provided by the CodeQL libraries for Go +only models `local` control flow, that is, flow within a single function. Flow from function calls +to the function they invoke, for example, is not represented by control-flow edges. + +In CodeQL, control-flow nodes are represented by class ``ControlFlow::Node``, and the edges between +nodes are captured by the member predicates ``getASuccessor()`` and ``getAPredecessor()`` of +``ControlFlow::Node``. In addition to control-flow nodes representing runtime operations, each +function also has a synthetic entry node and an exit node, representing the start and end of an +execution of the function, respectively. These exist to ensure that the control-flow graph +corresponding to a function has a unique entry node and a unique exit node, which is required for +many standard control-flow analysis algorithms. + +Data flow +--------- + +At the data-flow level, the program is thought of as a collection of `data-flow nodes`. These nodes +are connected to each other by (directed) edges representing the way data flows through the program +at runtime. + +For example, there are data-flow nodes corresponding to expressions and other data-flow nodes +corresponding to variables (`SSA variables +`__, to be precise). Here is the +data-flow graph corresponding to the code snippet shown above, ignoring SSA conversion for +simplicity: + +|dfg| + +Note that unlike in the control-flow graph, the assignments ``x := 0`` and ``x = p.f`` are not +represented as nodes. Instead, they are expressed as edges between the node representing the +right-hand side of the assignment and the node representing the variable on the left-hand side. For +any subsequent uses of that variable, there is a data-flow edge from the variable to that use, so by +following the edges in the data-flow graph we can trace the flow of values through variables at +runtime. + +It is important to point out that the data-flow graph provided by the CodeQL libraries for Go only +models `local` flow, that is, flow within a single function. Flow from arguments in a function call +to the corresponding function parameters, for example, is not represented by data-flow edges. + +In CodeQL, data-flow nodes are represented by class ``DataFlow::Node``, and the edges between nodes +are captured by the predicate ``DataFlow::localFlowStep``. The predicate ``DataFlow::localFlow`` +generalizes this from a single flow step to zero or more flow steps. + +Most expressions have a corresponding data-flow node; exceptions include type expressions, statement +labels and other expressions that do not have a value, as well as short-circuiting operators. To map +from the AST node of an expression to the corresponding DFG node, use ``DataFlow::exprNode``. Note +that the AST node and the DFG node are different entities and cannot be used interchangeably. + +There is also a predicate ``asExpr()`` on ``DataFlow::Node`` that allows you to recover the +expression underlying a DFG node. However, this predicate should be used with caution, since many +data-flow nodes do not correspond to an expression, and so this predicate will not be defined for +them. + +Similar to ``Expr``, ``DataFlow::Node`` has a member predicate ``getType()`` to determine the type +of a node, as well as predicates ``getNumericValue()``, ``getStringValue()``, and +``getExactValue()`` to retrieve the value of a node if it is constant. + +Important subclasses of ``DataFlow::Node`` include: + + - ``DataFlow::CallNode``: a function call or method call; use ``getArgument(i)`` and + ``getResult(i)`` to obtain the data-flow nodes corresponding to the ``i``\ th argument and the + ``i``\ th result of this call, respectively; if there is only a single result, ``getResult()`` + will return it + - ``DataFlow::ParameterNode``: a parameter of a function; use ``asParameter()`` to access the + corresponding AST node + - ``DataFlow::BinaryOperationNode``: an operation involving a binary operator; each ``BinaryExpr`` + has a corresponding ``BinaryOperationNode``, but there are also binary operations that are not + explicit at the AST level, such as those arising from compound assignments and + increment/decrement statements; at the AST level, ``x + 1``, ``x += 1``, and ``x++`` are + represented by different kinds of AST nodes, while at the DFG level they are all modeled as a + binary operation node with operands ``x`` and ``1`` + - ``DataFlow::UnaryOperationNode``: analogous, but for unary operators + + - ``DataFlow::PointerDereferenceNode``: a pointer dereference, either explicit in an expression + of the form ``*p``, or implicit in a field or method reference through a pointer + - ``DataFlow::AddressOperationNode``: analogous, but for taking the address of an entity + - ``DataFlow::RelationalComparisonNode``, ``DataFlow::EqualityTestNode``: data-flow nodes + corresponding to ``RelationalComparisonExpr`` and ``EqualityTestExpr`` AST nodes + +Finally, classes ``Read`` and ``Write`` represent, respectively, a read or a write of a variable, a +field, or an element of an array, a slice or a map. Use their member predicates ``readsVariable``, +``writesVariable``, ``readsField``, ``writesField``, ``readsElement``, and ``writesElement`` to +determine what the read/write refers to. + +Call graph +---------- + +The call graph connects function (and method) calls to the functions they invoke. Call graph +information is made available by two member predicates on ``DataFlow::CallNode``: ``getTarget()`` +returns the declared target of a call, while ``getACallee()`` returns all possible actual functions +a call may invoke at runtime. + +These two predicates differ in how they handle calls to interface methods: while ``getTarget()`` +will return the interface method itself, ``getACallee()`` will return all concrete methods that +implement the interface method. + +Global data flow and taint tracking +----------------------------------- + +The predicates ``DataFlow::localFlowStep`` and ``DataFlow::localFlow`` are useful for reasoning +about the flow of values in a single function. However, more advanced use cases, particularly in +security analysis, will invariably require reasoning about global data flow, including flow into, +out of, and across function calls, and through fields. + +In CodeQL, such reasoning is expressed in terms of `data-flow configurations`. A data-flow +configuration has three ingredients: sources, sinks, and barriers (also called sanitizers), all of +which are sets of data-flow nodes. Given these three sets, CodeQL provides a general mechanism for +finding paths from a source to a sink, possibly going into and out of functions and fields, but +never flowing through a barrier. + +To define a data-flow configuration, you can define a subclass of ``DataFlow::Configuration``, +overriding the member predicates ``isSource``, ``isSink``, and ``isBarrier`` to define the sets of +sources, sinks, and barriers. + +Going beyond pure data flow, many security analyses need to perform more general `taint tracking`, +which also considers flow through value-transforming operations such as string operations. To track +taint, you can define a subclass of ``TaintTracking::Configuration``, which works similar to +data-flow configurations. + +A detailed exposition of global data flow and taint tracking is out of scope for this brief +introduction. For a general overview of data flow and taint tracking, see `About data flow analysis `__. + +Advanced libraries +------------------ + +Finally, we briefly describe a few concepts and libraries that are useful for advanced query +writers. + +Basic blocks and dominance +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Many important control-flow analyses organize control-flow nodes into `basic blocks +`__, which are maximal straight-line sequences of +control-flow nodes without any branching. In the CodeQL libraries, basic blocks are represented by +class ``BasicBlock``. Each control-flow node belongs to a basic block. You can use the predicate +``getBasicBlock()`` in class ``ControlFlow::Node`` and the predicate ``getNode(i)`` in +``BasicBlock`` to move from one to the other. + +Dominance is a standard concept in control-flow analysis: a basic block ``dom`` is said to +`dominate` a basic block ``bb`` if any path through the control-flow graph from the entry node to +the first node of ``bb`` must pass through ``dom``. In other words, whenever program execution +reaches the beginning of ``bb``, it must have come through ``dom``. Each basic block is moreover +considered to dominate itself. + +Dually, a basic block ``postdom`` is said to `post-dominate` a basic block ``bb`` if any path +through the control-flow graph from the last node of ``bb`` to the exit node must pass through +``postdom``. In other words, after program execution leaves ``bb``, it must eventually reach +``postdom``. + +These two concepts are captured by two member predicates ``dominates`` and ``postDominates`` of class +``BasicBlock``. + +Condition guard nodes +~~~~~~~~~~~~~~~~~~~~~ + +A condition guard node is a synthetic control-flow node that records the fact that at some point in +the control-flow graph the truth value of a condition is known. For example, consider again the code snippet we saw above: + +.. code-block:: go + + x := 0 + if p != nil { + x = p.f + } + return x + +At the beginning of the "then" branch ``p`` is known not be ``nil``. This knowledge is encoded in +the control-flow graph by a condition guard node preceding the assignment to ``x``, recording the +fact that ``p != nil`` is ``true`` at this point: + +|cfg2| + +A typical use of this information would be in an analyis that looks for ``nil`` dereferences: such +an analysis would be able to conclude that the field read ``p.f`` is safe because it is immediately +preceded by a condition guard node guaranteeing that ``p`` is not ``nil``. + +In CodeQL, condition guard nodes are represented by class ``ControlFlow::ConditionGuardNode`` which +offers a variety of member predicates to reason about which conditions a guard node guarantees. + +Static single-assignment form +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`Static single-assignment form `__ (SSA +form for short) is a program representation in which the original program variables are mapped onto +more fine-grained `SSA variables`. Each SSA variable has exactly one definition, so program +variables with multiple assignments correspond to multiple SSA variables. + +Most of the time query authors do not have to deal with SSA form directly. The data-flow graph uses +it under the hood, and so most of the benefits derived from SSA can be gained by simply using the +data-flow graph. + +For example, the data-flow graph for our running example actually looks more like this: + +|ssa| + +Note that the program variable ``x`` has been mapped onto three distinct SSA variables ``x1``, +``x2``, and ``x3``. In this case there is not much benefit to such a representation, but in general +SSA form has well-known advantages for data-flow analysis for which we refer to the literature. + +If you do need to work with raw SSA variables, they are represented by the class ``SsaVariable``. +Class ``SsaDefinition`` represents definitions of SSA variables, which have a one-to-one +correspondence with ``SsaVariable``\ s. Member predicates ``getDefinition()`` and ``getVariable()`` +exist to map from one to the other. You can use member predicate ``getAUse()`` of ``SsaVariable`` to +look for uses of an SSA variable. To access the program variable underlying an SSA variable, use +member predicate ``getSourceVariable()``. + +Global value numbering +~~~~~~~~~~~~~~~~~~~~~~ + +`Global value numbering `__ is a technique for +determining when two computations in a program are guaranteed to yield the same result. This is done +by associating with each data-flow node an abstract representation of its value (conventionally +called a `value number`, even though in practice it is not usually a number) such that identical +computations are represented by identical value numbers. + +Since this is an undecidable problem, global value numbering is `conservative` in the sense that if +two data-flow nodes have the same value number they are guaranteed to have the same value at +runtime, but not conversely. (That is, there may be data-flow nodes that do, in fact, always +evaluate to the same value, but their value numbers are different.) + +In the CodeQL libraries for Go, you can use the ``globalValueNumber(nd)`` predicate to compute the +global value number for a data-flow node ``nd``. Value numbers are represented as an opaque QL type +``GVN`` that provides very little information. Usually, all you need to do with global value numbers +is to compare them to each other to determine whether two data-flow nodes have the same value. + +Further reading +--------------- + +- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. + +.. |ast| image:: ast.png +.. |cfg| image:: cfg.png +.. |dfg| image:: dfg.png +.. |cfg2| image:: cfg2.png +.. |ssa| image:: ssa.png diff --git a/docs/language/learn-ql/go/ql-for-go.rst b/docs/language/learn-ql/go/ql-for-go.rst index 2528cbe478c..a0e04cf0370 100644 --- a/docs/language/learn-ql/go/ql-for-go.rst +++ b/docs/language/learn-ql/go/ql-for-go.rst @@ -3,9 +3,16 @@ CodeQL for Go Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Go codebases. +.. toctree:: + :hidden: + + introduce-libraries-go + - `Basic Go query `__: Learn to write and run a simple CodeQL query using LGTM. -Other resources +- :doc:`CodeQL library for Go `: When you're analyzing a Go program, you can make use of the large collection of classes in the CodeQL library for Go. + +Further reading --------------- - For the queries used in LGTM, display a `Go query `__ and click **Open in query console** to see the code used to find alerts. diff --git a/docs/language/learn-ql/go/ssa.dot b/docs/language/learn-ql/go/ssa.dot new file mode 100644 index 00000000000..c8bfb8c62a0 --- /dev/null +++ b/docs/language/learn-ql/go/ssa.dot @@ -0,0 +1,15 @@ +digraph ssa { + graph [dpi=300]; + rankdir=LR; + + "x1" [shape=diamond,label=1>]; + "x2" [shape=diamond,label=2>]; + "x3" [shape=diamond,label=3>]; + "return x" [label=x>]; + + "0" -> "x1"; + "p.f" -> "x2"; + "x1" -> "x3"; + "x2" -> "x3"; + "x3" -> "return x"; +} diff --git a/docs/language/learn-ql/go/ssa.png b/docs/language/learn-ql/go/ssa.png new file mode 100644 index 0000000000000000000000000000000000000000..cd5ba3f29de0c7a94c500544a285d5cd873400ce GIT binary patch literal 68479 zcmc$`c|6wL_cgAfL@K1gkW2}cC=nr3Br->XjHwKnBasp^CDLRnbEZN_WF8A8G9_e4 zTjRrF0}JgFO^xR31qQYf^f=u7>aR+ws{_FBe&e;Ok@k8Y4! z^6#G+wG7LWB>(eAzO0lZivRxT9pS}1yqqDPf-0^{oN5BT*Q?#e7&Yq=pp789pYHVw}e)Z}SR`K(zczAgB zST@rxU%vcob8=|yyrG|8^7Kxl;-Ho^eY4(jpRXVCGTQC^7Jn!-Vkx?UEK<~ZM@&q( z&UY2~e8{uyZ+(2?x#O4BqPusGeQo5Ko%{9C_2*Z{k&h)e&on#`5WD{5$xbyjHDe14 z-_Nfj?=3i{9ew<^z}YJ2d>8BEM><4ODP8PYb=s!7GHZjy@zcBBS)vtFb z{@{(b#U7WOMmje|OFGN9Juz%d(cve5yul{EUTQO=R?+Q7IfCwr0G zgnY)SB4ZmH1|cCKgA*qLIRgEX-v|l_l=(8SWtvvet=q6c-}OO61gp$c&ob-I=b;a` zaWDR)O73mZQxd$>M`=k@IdbHnwl>qPurT|vKBe1t?g-3vS65f>+O_M-vuAsQf`Vd_ zl8&CTYD!qSXU`t$-K`I$FZnh#X`7!p)BpR&mu&(9T5fOd?l@82-Mx8k=9hBG<+-_kB`Udr5(-8$?^90U#X_9-WaD8IPQ7*y^4PGaHps3 z<>{}D@#FhO)^N&HUR$xo4!h7<;7p%)zN@_G(yveFy^iZiN=kn1dLe!=XyesT9_2XO zkHv3WTaT8OFfeM(h1|P$9eZh3cXx-w$AoXKkJ;Sa-AB7zKK4$H^*dyUcuYHC;TV&W zl4^qwFGhkcXJ*P16^#e`%X%xWGqSM-PEEO*TUZ>OIsQ6QT>0Kk!?*d4XUKjV7C6a8 z?zMTFq|WwrXh>*RZr`2Tx3>rh(RJxmy0^Q}w!84yH{TaH56jnV4#Lxwmz6C+ z*l621aK{z&V!W@)$5 zH*Z#Vy>Pi68X9_wDKPE%^Nl#Iik6nC_2m2t8l~wxI&xpao_nj>{VP|Ot&rEz(OK#5 z?`L_hv-9Nk6VFzen3#n8;_1Yve0XM~aC5UXb#8k4_WDTiH7i!Lhg|wL)?dRTA+ho9 z-Me%R>VMZyBQxa`$30=A>Ic%7GI2}=UuV$FhnsvT@mv_s@0GqZ`ALPD3gDfcKNWV_h1uPo-$Vz#aQRMW>E`BUkng~U zWf`yjepO3L>%O?{=K1*${d-Iw*0X~xOE8@;$p$q$Tmik^~Wf<-WEcpxp| zIq#lmbmrVSe@32z#+81I8%51&AI_&GJkof`y>H*9lKE*N5~sIs-&VDybQE56REw5m z`CdG;bNQ-`Te3xjkiUP9_9|>Y_LN%6W#sk=P6@j$Mt2t9cp9BVtj%F=(SmoGQcW z)b{?Gn`0krOSoiYHj9Xe+@?cP$AH z4&EqYO8xWaPu-BGy|+{oC0s_>o*S0&z+uK|Gfvt(j)fAma{+q-IST8ee&eV*^ZnPIwmGYy$8C2Rd1rDvd%Vg=i3gmvawaPwQU#~8KEn2 zF*W5TxoB?MSx)`%Vfw%g!qqq<`5R~#mqg6mI#t$VdRx&1PH zt%Tdp|+L4F5c=4i_Tj2T~nWyX4OYGa1vR&uj z^voxxuA{^J!n0uhYD)nQ&PKVXMGUY^+z5Ew`^G5PHS&-U%BDtsAqF7EvsAfbDrlBN;) zS?9YXtvhlCb6@{FRpeII)x|-g9=neR5F|A+Ha4~$XU)o!Gl+d3lT~Yauj?{y?TA~q zn5^3~mk8-UQPk23jp;^C_V)EPZBEwWP6)em_wMoy8#YAkb3CYt1a~bmk_~&)_}t!% zvFUF~PSKsSP5tuuvnc{`YUIWD(b?aQ`CkZ5c=c-K;d?tzGv{7??ztedblEb-jT;Sm zr#QvL#MB<_-(=)5!Gd(F8x`V5$!>1etq%`c^uPn=*wHZ&-9-&f!? z7}w{m%SP}Q9@rr7JO>cbz=QZFPlA7a^yHkMpI7Z-#}kxzc`coqn$mr~^6d519BVgk zK9#1dX;^ZZ11qSargrsTVu`-K z{>gj?CCzuu&EAh5@uSqn#K-f<7o>)&CeqT=UwicEQK!aLG23o-tF|XqSSlqI<;5jP z(49z2x%|Cbdi%-eYmosQhFDoy@9%Tmdi2Rje}KR=362&T{E&xt_wX3QTh~cH!l%&E z(WSO%++x!DHuiH+$Nl%fz4oW4>1%6ishv-pIAQ(a83S+>6PMxZS!7&07Z>G|C!;zG zu3cN^b?q98TWp{C-#t*(k&U1TKfM2Ad|dv>k>F0pB(-oa+v4B8W~Y+1QOSI3GP1Uy#c{E~%hK8;eFPi)w9{?0t&lTOL zsHD^ze^aI$Ax8yGZ`TNY{)0 z7vGC3GEFM5Ta;_{^=jl(e~om7{7P(!Q=+G)rZ(=#Ifsvk>kyQZV(aeire$EbbK?8Q z5?NA|a;@}P_;nu4{QBM>rXf?NAv?#LCxcpp>^mA}y7=O{ZCz+k_W z@g_=NFm#37A&O#=t^4iB$F)4PrV*KeAp=>@ps{!m7?9X z=TJG3YRZsKw&(2(RY78;#ZhJ9kDneMxF4H%_+H=OyGMUg8=9-DfE|G$!G4w1{J9H{ zxMWf^7C(#OVAmyW4-_eU$*m8XK!VbJeSK>;ZF=P^DG-HC!_oo?UG-6EAhb4&OiZB$adC0RW@bEjvFFXry+cCQ&W_g!GsMNNrUG83UAeL>R^j^FR6QX% zX#s(iz%iAndTCR0xBeosD9IlQZif!7L>0`m?>|^(ZRPCjOv2g7b588%#DtQn3WK`2 zIWHO&eiyUi%X8CQqM}SdPTaga+m5KuPko@n)KBP zmsBD%d3LOw*^Bys=-oe3@oSdA1{(e~eKR?M$mJ3t&@ZZG%=sB=a-aXQ&!Dh8<@;C0m zF-Ib+#An7L8R%S^of081Q_QNBR>n|H(YXyLO2mE2&ehcwadViLDdEwh?AZAL;81Qp zKAKafPQ88mHY5evyS$-c&ECCxk-^ppaQ#I$1I-lvmS4l~uN}*_h|SE@v@q1y-%wm! zZ1CJJR^^qS_fEqCZ-9%wzN$d4i0tg$^WPWd*Ax^KkkwY&wqr*XvU8Thfa*FHmX(wp zC!SRz%ZQw7;$>`V*^!cxa)0-k)!N$H)JXGU&-3$5P!~uOOFOvu-hQXjE(Cibt&NV2 zl>uVVXiPn`Y@tKua-I2>r=+T^n}r1_tE!^GUwIv0n4inC{U~!kJlsDd$j_2{#}0;_ zJ9kPreh!M6e7bV@`}dpGH;_l3od4V13A%^H0TVg{p%qmQ>h9A{S;w~5`pUg~8%`Cva_J1cja`NVKsprraz?E?>(;L? z|8FJ6q2?l$`1+a+T!wQY4<4*0Wm3{v^}Hc>=oa95JcFM7-$sr*-%?+vC^?z-d(p4W zsNwv{I}9?Z@O5kJP54qD2ea>6iiGg#^XJ<1$jHck9QCiQk0Y@a$)dMz-RhxG0#HX+ zT1G@f5Cqwpery?ju-d{Xe6(xU)L^4R@7?21&O6(<^u#mkt6^bb|E{)q^MfR}Q>Qj> z)p!tu6B6#MuC7k{HcrpkEPO-i_i`V4G@X@?Pvn`m0?-90TwfiF-SH6%yJetSw$^3K4pIR z{qCU6(yS#5^DpY%(EVq+d_VO@CsFd-{M-x<(e^hFWrefPpFQi>-fl3m=74S>@7As5 zI5lk03VR)G^oAbV_H{JeD7Z0j0|BUrhjXp zE`0+1{rxy@~Y z!ly0Dy>$LJ>jdhTfx&&_Yt~d>+cG#&225;hcE}g_4*vhKJE}k_s(00^zeoA%i^n@Z zcLfFpia1krnyN-RotENSfQs8^L#q6g5_FZ6lm~ zKE7Dzp;qjzrR(PXu2+z6O!4133|(8!An)obA?Zv>=rjMBdVLM2>8o3OEb}F-i%r_^ zGb{dTi)?M=P6*=ptP-Mfd|vzDP#a~*n|M?FDOq4Lemqd$Ix zy~y9bn5#m${l^pB4jiCbzvDP>wgo~3l)}%Et`jZxe!4qlWjT?iE3(XL%v%B40(g{z z?U)t0`Cir5mKR?9Vb@c-B!6PD&%WCb0RbXvxZQjbv#56iq!x?xxAbB30AF_-R3c|qN zX1pNkpw~ms`EZ7b<8RPYb8&Hztw1%WnE<-|`R&67fQ)T|f=pb06LE`+pojJxlIPd= z+5G5H#!ILyEwO?t2q~pkwIx*yP_+>~VQ0}LeG6%%8(>lHMDA3h^PSI^h>MHQP7h@` z3^DmrU%h&DmzWsxO==1_I&x%yYaMEefh)Ffb1$_mnS1t6LP&m~-4#YbGmO9pP*dQb zDxROV+S{B`_B1oI6!in`&6aE#^!jKSjwa|TPAHr^C$MzsQe!JCp}g2`RL5EDzF$y~ zxk6EJ6BtVz!C+3=;3tMJ=qQ7OgPD1G*RNk+F+M)7sG_nMrxT&I5tN7S<15j6@@G%Z z&wMunyh{x@per;n{GJ(P<@Jb&YMt7;v&Qi(ApY%pz2P zr?fvm_NUxNzF5U6!(MZf^WL$WK|$V%+>8P&T3w;HZY@RWNJvPawM2(XNUeXHpHM+m zaMD*9bw?}i4yc>FV|AS{e|a->Tr``4&J^$%r@5)>74Kj6HX zoH?@si;Ap&i-Mgw@&Z!hF&5hjeY#BKI-?7>HUa2eX%f;8apo)O~@{X<8M)@=yOl z;6GY}rGNStj+TR96*uhPzke+on^4|JPtO(f*M$?UCj^iD^J+okNNPAtr&%dfYuBx- z^p(`&qh7w8u9}fB1AKgZ+=9A)64wwHTad9| zM~E>ugH{3_zJ}bs?V{-B#bnlEuX--k=*0yFRQ`}-Y`ZO1B^`-Q4f?>?A_W%JAlu?b z{qchbm!na}OYs&D4_gD@83U()#}AH?F)pP-lo+?9>Y;N)5^15q$;X*+SWvqa8A-op z&6-sllIxI;n7KIqej$zOriH%Y;h>ifH`wQvz<_{q@D)Kw$15$7{|vHBY3}Ycq;qyoJkKIOq2}bYhcJua zGv&Swd{5&$eD{EYg2F#dx$a?s%d>Sp^czO|Z_3uDdrS{LvQB2!3k6SuL_#?8;>oEo zGgLFb`vEGskR;ad^Yde4)z2$<;GjQu9plD{L-iDNbaF!fvm7;^CKs8__0lD?w=r_h zod$3H8~)F> z+t=n4W|`Sh1+^%NPz|c$vgQ<>v3DA>cR1NtS^I#yXCva=)CKR5>PQmC*r!*_a$P9p z;CbvE9m6j6`zIHy=9F25RqrhJIHCEjsi_<=EX!@e@~o8=>9GF%ScZO}vq^oFm{|7a z%@K=h85zaXbVlxDK5^&eoE5FDw|}k=C%x&}bLYzH>sN(`hkN}P9v()Z(xZiA)NW-! z=zr}ldQtBi1dbNl;NzF#cl!$-kTm4(?uGxmA=mu~riman@Ep;`%qOWbb90px6{+2R zjqLcR&ZY9LlbYw-vgJThYQEqa|`X(mwAw$)+LEZ4V zBcw0bH?FHZJ6f^kzKn+?mGSJ<*wpVY4^LBoP^!IGGMhi3($&#XIC^yb@tm`v#-ik)x(E-zkIol?D5JbInVk%6RA#ES1gb=sClwL z;k(bg%|4?chjc%*QN~>Y32PJp8mQvWVGcD|*P**0?yp$Rf0OM#KpdB_aK`L&oKS~` znZ7{bo}M1f%Y~4(_SOlS%+LN7t$Fq86%wzP$~iyFk=frr2&646Dx&ER!c!95UUyH} ztgq6an~!(;%=eqJ^Ha+JK%t<7rW{Ia8V^+hYQ?`T);B$!mk?#nydhkys1-gLpJt>k ztnN&jUlR+9tv}BBpxKVI@2_@f5Jo))cN!sX8yw6bl`3cveH0`fI;LI#fB`FfZ;kjz zcOFy0xKyF-+r0rG(9&E34=Gm!&y9$IwdL=C6 zN(vH&in_WFA|(e2O=Vj!Do%`6JmI7-^$T-waG<$e6KJ*gW0U9YKvlKIE+-cu>AvtBY{vp9ThArQ0u4 zA3&=?RQ%I>3ugx(JtRFMqfTSwo^wsqQ1jBphj13I{p!B72F%yl_fHd^kTGu^vwi=RZ=^GSnX_~6rH=q0nORv& zMjKR;K`-3De?OU5xaio03wx1kgxF_9fm#5T<3V8j3%BSTUL4dQMe)_1X0bhcAn<3h zK8o|KPH~@ne+F{)x@O3mnUFJ9Z4#x17s0EzSVr=~u%CcVk}()cqN`u*2E%vfV|Hv) zV`Ev2+%@yo=f}>?IRm2;zy@ZJ=urS0)C}z%+=7C12vAULX!*fK%E`+EjV?4n8=UPIxEzmhYYFVdDl&RNF#*RMq^o41i(rQxCM1}WC3XuQG05r~XZy1tnooZ-)(PS0PwP(X6? z_Rjr)l1bFgvT1!I55B3&2GF^LFQ&rj^~ulAR~6N6xxp#B8PaFS%uI1i3>7jI90GaT zo~IVQHK7j8$tm-eJQ*lFVs!5`yP$m$>1e3+vB<@7bATNiw-O)<@IV-#^xS zowFQ(=zkKXs-sGxHXueE0twxCOw9bae;1;S?#%UfvaL@H1A!M_rAP0-$Ru@Pc$@6y z$>B{F_4ls=m()jy1;)2huH1Y0mgqP$D{uUtyKz0`8y2Z+5aUR~12sftK|W$(N{=q^oshc;egQM9*-=DvQjnv)c^@x_5ow8b)vDVs&hfl*`Sg-8h(qeA z#cRAi*yF1Jw6GgMj|v7+zyt849zyIu8z|}kV(DKlOiwdAoB~5m z$iB<@_N;o{D0EpKGZ&_2X6PSiyAPrds|GSMhWW_W))wHX?^PJT>(nS0SWm&u7_b3r z!L!EI8}JWUzDr_QwQ7}l>!~@n1YdrrB}j~wmHy0)@Cy-|p8rUc=2vN89LBY4ub}s; zvq=VzX@;}9$P)xq2W`3r(@tHwwENWB2M-<~6o|$j3lR>YPj>976~MV=;8*cUSMJ=o z6Y~I414zP(ii-H7LC%YXE-pZC=Fmi39QW73!B_ilM1_WO{Spq)-8VKiwo%OTwy~kQ zIs>U}U|oE64*|U1AYaL`Ks+lZ@W#+J%ve_Ij~#LzpmgL4q2`{vTnHw(5IK;0Yh0UF zRTzZ@DU~5AI$8v<4nCFqj<$TXuF$JU_b-Pt#K7r3x`c38ASzmU&tJP67PgFZsxMqL zEV@AY;0%ra{OMg%QX>ETB9tgV18(Sp0QTE?bICJ_EO59cp2dcH4vPti3rmJDX|!UX+o!amepIP$V8%g_j8@gWd+# zfMzSfcT}qYyZjh=)(hB}{<^L1-+uE@3+KYE@Nfag&V)nE;P{f`7A^}NO?Nc|&jfdYh}+MzWz+EN ztdm*lRS7GJfTR1b5yQ}1nuZQASV4Y`!TbD8-J=Ltx(1CSM|`8BIS6oNfGFgQT!uq% zgTa{wy(&|;$1lUOY0y?It(qFDs`7|`kghAPAR`%ndKn6CT>oX!peJEj6B2kqdu#1# zI=tA`p=gyAd(0@R{w1l#bzh{+LkA5vV`dIxy?*Yi;I!*p+Cy5`XmpFO3^ml$(vR?_ zR>1(U)$t_T1Fxil`1JHuC<~R~sEona0*;tq`3JJ2=)tf6E6812-b*BuHmIpQki9?% z5*;M9zwHu|#QOS#HT3jh@7W6rcAk8Gr7>QaM@s5NQ-%QamCk%ep%(8)sg2Fem7wPd z)3u6iubO6w%lFMhTSb%>O)~6SJQms~U!pjgsgP zpcFc^)9@DF+jm4mL;394WR-JY)h&PcmI2 zXE(@Hj1SbsK7PDIzQdQ`SM)(sU`guQAQJcV^?9L@u$0X@rK?Mg{vEhO4!S$~fg04O z##n_F1ZqHWCH(AKcJ?527z&?r@uj7BKbYS5e56G*7T)1WD{E@ZP(Y@Jvm2-*?;KQ8 z!cr}P7IACl(DJ`88Ex61i`|ui1gCeo^N|K8(OR_fS+^_IZ~X-g4!%C~R!NtU?b#`b zarQ|Cl*fiI)`NO7t%+G)2@e(m6fEnbb}dQ~SPP=JdPK~UH^hdfI(I=&GXvob@KK4K zXv7oKH84Q7MBhYXON&#<06WQ(*0~f1)Y#ERWzJsUBZnbq(#m#rnZ~O&E*^js#fdYi z8`iI{WgntYS|u0+4#I{=Z3RahBiBlScWD}_%mO+PLa=z{z6Alqn)Lqtdo<}R&B*T8 zVV$xx6bH`>u?=*_cPlmuRZnm4RdkWGtyswuk1y#AsR{2&R&GO~kd-tyY{P{EL zVkO|~X$pE*qTV5sr#W@u5cSmF5t{lOY5NurqgqrAPYIB?s1;fRy#ir94PD)JtroCI#J@1uA>K)7L z@U}1@Ce}(FOayU4AMvHCs)|^E&^8ggU?`X!$w%%W3O(N7Xm9c`68 z(k@y*Gw@Gvvz8)*5*}JuSQtF|%fctX;AjJpBIQg?<5UKR9zuEU0Y$cJ@7`)~Pp2)3 z7wXEAW#+ALx9mFeh8?I>k1|bYHqeGA2TmfWL~C$t9*>KCop@qY5)4Bqin+ph1tO11 zOGh&-7WKH}aVT#33%BOr41DAIgzr;P8JF!3?bHt=-9%c&D&t>v zd11~4R*e+xUpVRM<2n?okm%?gj-AlK1dXnJn)$`1yK?19FE`>e@?5x#>OIbUX0h+e zRl(tcNP2hQUDd>waOl}@NzDhDPv827KWEZT0w{XPo@d#jn!u~O!Qj|2lY!bhe{IS= z0|R=4;q_3Rra+0}WrWUBV0I^X7X7VXV4%*ypKcj|+q*6551=d_3}*KSNA*fN18{c= zRtlOSu=D%CY{uregL%2P58^{X(@0AQ8s9S5iviQUt~325cJMnUO$mqoA#dUWP};g- z*(w_z(T{ZJ4TfS^%T8S97Jb@XzbI{yIQA-slAk?A_Vc2lx0{`^H#avYgy2`GQMpg> z&ol@Pn8213B`IdU&B)W_=hw#jdu>>WweHm zHE;vodB!+W@`aLT^I<(Pyw!TJ2B3XQKb}kHG5xa)yG1=g^mN!Zk@y{cscjyZ8{EM67frh3@j(x+Y`w`LgvWZn4&B3@x}Z#z8n-Lhz4@xFO;4J>)5i6~DRgr=sZT`**X{$=a5PNPjaj|A+9 z{B%5iSHi}|#zxT^`t{q_3ak{UOS6pvh>Zo<;ZEer8XOuTi2)Ub_~b4Ow-YnA;N#yZ zPoAuHars3T=?TM44UV6PO~;=7?o*lqn<&@dKJKkpBkQdzNHf~NJanhA#M3j!`n`7M z2#yNMnb4kobe{HTC#Vj9i<nT)bFl2`={mddPp5F1@OKfXCHllH~ehS^mXs{s+$SIE=1U19DvmAIyU@wREckw zn7+V#KCiECf+h&N*-4+sV&d`<5n%)+hVg~aPDePHy$*$K<&u;QL*xzKvDz`C|0kZV94S4u|;nT*=Ic6gr>G zrf^PaH(r;*dhj$RmX^l{hcpL@7UpN#i!QnR&H{x6ubh&aBK*dOn86jNA8gaq*S}s= zB+bjTvfFdP10C$PZHBM0Q)@^{MawhLS_9TABqU_HY*I2TBY*-K()>6YJO_i;rk}B} z=!3B^^=Hu^Qx50lDU&<9i;1n8*y=H0veF&yng3WiB- z?LRbKOX)XO>6GqxRAgWJ`7{7;O9UkS5rGNLm7hlLt2s zgX2~3@~x@hXYZpi1du~O+>ZQq&*<`1L?MV8!HK!_Vvsqo?|Xa`zR2KAm6@68+HbWm zm$nsuz-uYOCS4uOK`$#?!fKcni*1%eT(4zi6+D|fwAekO@L4D<`qz_#Q?+!ufLXf= zoWqU<-n^NiwS{RK(lb}6$|&$DUBf=m5o*h-;Ew{VwJn@PF4<`yBq&%8kE~#{Eyx~+ zwtn=&9t^34I0oE8LWeDGM0T{u!cIjn(dd_lp4> z$8%^AF}>BTxt&Oyz9{cy9UZKfCWo(riE0m}c!SY3MhPbV8-xJO1nNDPm>3Ii>#Xf! z#OhveNlsZ!1!m7X4B z&`s&uZBNeLK7i?-?x~K#!u@dR(6EW0zkOn1_D91QOezlX@-&wwtkUs`wzG;$TNrTS zNJb-~K5DHo4&_-C^7gFMdQcKzR}MHi<#c`*L92cMq}8W4_qUEAs%RZQ*Ix|}-vnxO z;7uKWY;y8805oGzV_p&e?}O;8bwz^f4@2ijxp&D@+EJJ?v^d`_?KW#zuO zo5+xv=C7Ebc;}WczYY1Y`X=X1q^lfsqfNhNKoaeOvphT($zN~k=RPVja8NQkPLD(< zH#CHv6FxWKc1A(qLu9po9q~l3b^Mro^1Lwq9jqWHf(q5!5Hor(D$Gpdwv&IDh1I1~y+9G;@>g z*@T>G)8&T*&b)r-NrTJqNSN(+9i@V>#hnya3ulTFMxVBXs`PyNM2#|>#glUK@?{we zU@&-kdgebYfYJnZo0@PVj7_1atV9ojE%tKUR|cZyii_vbEu{1O$J@Ht@Nlzes_A&3 zh~M9T(cyO%0_6P1Vg`Epz=%@?WhOe&ryhAO%wvdar|bh@0~A&+Q|{Ds2t4s<)=g`Y zSpW^-y7vNLTKSLp0*xf=C$=@F@1NWAkXi%se>6-uLkkL4Y3TvdX1uJcV{Sf?bM`9! z4AidluN=gkXH}>rKo!I$zWU(7g9A0hoyWkSSDEPlb>XnO`kiyh%huLcJn9H!m{`cl z%d3H7ymx4b9=d#ZN8LkCxHV=g!ve7WW#}DxdwZ>uOAflZNn(8F3R;zwtQ2^j3CO|R z8|)WHvq-}s0z?V!= z95#&jlp^-p{Of?x7W3KDvc#AukMW1elpzv;lHr47xw9m1tx-im33eQTmrmXOIAK!R~I zh(+LC{qOs!*b`swzyJ!{KHt3F6_Q;K)^Gl*|Xf108%}5yx6yS@%?H@GxW@ zmU^=}U{4979J)_7y2pWl21gGEL49(xD60_8Jl%$SBQX3%GKC)l?S}i@56Q>cVC! zKY;4k_b7MC2{=KDrzvUUW+3D6!ljV>D|HoXF(TkuR#CAGk>N13di81y7nGl{ElTV& zcm4nx7G~v9)`pZkIIt1*EVolHAioF{&yF7^_2>`UFv83fu$7&i-Ie%wvm#C(g~g{E zI4_j*?lG8Rm>{(+cJS~lTbTRq$#OB$Z3w_p@A#wX@A!YnrXj~1FI+(VrxfkA>F5E4 z3XGwMl1M!P^%J#d3kKuNss#n`31-znS}&_JQ26OobT7fgNQicj%8>+lWP(Y<&FI=<0Ojq1G1y8> zDP%SVP5iDsdoWz;PkZjr9UOid_=UnBZ9Vfk!e;@}8Fvyllg59nK1khFWC=L4RbvoH4u9{IE{V*ud>UyZ-n(z!hI^UGkk$13$qPq5ZKw-cR?{6 z36uY``MP-m7m}t+z#FXwOxP*g+Sn+EqfTt9K_6O;;=a1q`2+=8Ao_kdu)>ogIO)V^>vm#C>oc-FzH#hBG zPFPxCMxVBA+qa|JqB{Dn zjEd^&gBDMcf$@Q$-aMl9?>5Hg89cKNua77xk%hbTk7bR#KQ`4NG8~MZL7}S%nMds1 zZ*A!cn=>+iKSoa05#q2Jp1YneUsj+93YPSG^j9;0xZ#25j(u^Eb>4atMzrOt+5M2r z`@k*90db`{87*cWCZF*L;Pvcg_yJ%Igrth;OT}Y(ys1Bk$scoKu`w|*?vG($As#*S zY>H|JVW<0#iOBKL|27e&s-N$6aAc{B%1^5gxmE^Z?S~;G6pG>J`e}Q zJlSgFPf3T5tNp`=ex$wu%{p`@39K_WyQ@rn)^?Pm?o|8(hP#Os{z|4FNmf|SsOV64zAchEF7Fw&@9NzMy zss|SzE>#o{w`2=OT;Y-~CmnGcyuhP~nghT_;jkDv5^o%!Oj$?T!>KLY$1rV$;fAYF zf$AF~?@2m+y^@)^3+6oCiC&d;pl_~YpoEE;d7zb#X(b?@Zh`D83`jF>*l-=7r?RT* zRnW^z91IK$?eE{;5pTbQy7wvJZ>nakwM|`CiuRl6AjIo6S?HCymLTB^OR7M$m4S(oZjud$iPM~pbl5%TvoS2g^hfZ<@ z?ch8=Oe#=%m0*hoAsYggZ?Nszxp&J^czn@m9K5;tb))g(qopQBB)P%Di`pERld~s$ z0$B-_R$yjQF}EA+l|K?`U43^8jxfwYZj-|TrlN5LkAN;FxUdA&o4Nb%;XEs)a>@~@c8-tBPXiOeV7>KKbJ2`)Qwgt zN$4vO@(K@SJVGKPPZTGmrIA^5I2aDFF#1_0A}_3BmsktYQFMsBtdz?Wl@vcp@qhhB z8_Z@`2q@!)Ff^BC@tPInJS_!uhB9%8F|cjLY~CfvrNrlf`a+H~u~q!EdJMJ_=m3FE z3=@ECs%ol=xjvANA$+~Xg$G&j#HK7pooa=h1Q|2-M(X>^{T?kau2k+rBc5$-(+vHMgmHVB%?)(`)#uBz=dEm+!1SXD0BjZ1YnqeVLpH zYpq7^yCDj<6;f0LBsrZ5JUyqvGv0@bw$yiu88+0!*Nk+2pBc4Ob!-s(b} zik1pjA(nX%;b^mXVu#g$c5Xty4TdTA;tPs{a9&e>Va z!O@X8PhoG4gC38*Z`-zQ2O#CV?Z4Z}@xGg|EbyeF*}%LI8&uBaz@!^DZ6aD7TJi%3 zNEF^RAek~b?m4NA3#W?j*<%bb9#6Rb_<38~o7jAL$deE3X-!_^_eWuxq~9?F`V6z% zemJmy;-PBSDrCY;_umefqCIJT5@mkLk|m%Y%(*zu`NQ=?Y;(}DxXn^iQ;Ag=%R}O+r1K1oMtA!1Wg1uGJ~*PeR;_c0kUB>u0cir$_; z;o?#R7LEQKqdct^2CaHvPk^gJ5n%)gE+j1M8pw?O;2q#}Ifx+oAo2k&I5C*riE#v7 zn>WY^IAlP7U6t{eF2(g4hz#o*-fuT&11Y6-8nr;p{7qk4ajgVUzLU>REmzsu(Pc-| z4Y+dDfJISWUB5)T7^o_#d;w#`OxPUgyUbED2<}nW{TLZI{N~lmNW^R@oC{zdP5H-j z^8Vz9^v92nsnk62^<91vtf9LMClZ$_zm<(Dl9Gr?IW^|XP0%ho<*w%XW`G$Z(w#tC zP<48w3Q7eIbZ;c~IxY?_tc=;l<>(CH;68v}5J;1MTMP_K{x;e22@PG9bn`@$-4BPyp6^Uc8V3S*}=(lx}kR zG@t0$oDiqSPsYm_b#)qQRc{qpiPQk7whZrj9ZXdZ!T`FoGHl?$s+xLwe82VsOv`)J z8hzJ$0u3Hzz)pgF64i7sb1G?qFx+MxTRAXJKI>RUbi0 zUDOT>gcdG_86S6$yZNhap{`o*H~Z=pm>4Jr6=Hnu+)Dfhq((pvPbwY>xLFh@Nkvo< zkSjQZYmXBV5pE}MnQvTlXP^=o6ualYWx0#b!1tjgJtMM-D_RGENw^F&gIWEgE5al< z)Rd^OP<@!3$#@$irT`8X;4V}Zb=U47oCgq0R~o)tYxu$=EUeLI^BOKMn7ZupPolW{ z?{wSZP1DlS(hhop5E{Bpu8ANy$Oi*H=kDY24p|K#|K}zipi%Hj3<*g|WNH$>Br28k z;K63lc+}FBM&HHfr_C_J1tG$@z4b~4-7vhpRY=cD)72$zQIU~;1M(usg;U09UP!i&sg3JWLQ`>qt2B}vH$nfF|DJX^L}f?6FW+u?Rqr z@GzL381#!zN%2QMyH+<~ibdVEdv}<So&HC{%@X7~OjJe_R1!Bh)armSX#41LICP`a*c_`atAjCx6UW9Ht zurpNzmljo4SC_Z9-%m96&f%!oMMii?V=wv)R~TgZT#)yhCBr@N>Z?xz_=JVmU{NG4&pvM-LqB5*hKraNqQV3ofZ`^iJyHrf?QO!s_gqiFsEk^B1*-z+ zK;*Gv#a3I>jS8}q@m62RHgKC!O zAeIB198;wNex63@C&`*fFm!|d5_)=iUQ1`vR+3K)1V|#Y>mE1G3!vP{UF|{!g#mRn zthtFH4_+F~Yy+;rw1o&xNN8Fk{BbK}9^PECYb$OAy_>4qoDsAQ34e=d~ z8yT0pdyBEj0rM177yaG9y#5%8rf*E?Kk6!Hgy~AS@IW8 z1#-AxY7A%c>xkICTGUAN1?pUx_uY(QP}1?RBJNffPq1{4}`Evkk%7E{OE`&F5Zk8vI-a< zs)_{$;oL`8ejSu|W=L@1IPM)G+h3!Gc8gr#O~QymqQQ!Zs;G6OVN8IKdJ}E7ucH}I&&d5s z;M{kS5)MNraOHCUS8O>Yagw7B4$-Kjy)aC1o1w3t0_!oj!8hjwBp&a3_wK3Ks{l6P z1_dxQrUIL|62!2YFp};}H!3+bY~v0gTn@_&3cpmoAo$zjfX{{*w}xIjV%Q~i6^I^y z;_4{A2XG5jOzCCVP5kqKABFH+RErZ-4B&tOw^e5DJ$!f*q;W6I5vDcJbIbb2VB)b& z;Rx%9Vw6{ThZ21imblU1?v<65TXyfxu9_iJxaeHAZHrlhxJ8K-RXHqK0N2IIVt2y9 z!ilya1o&*MD>mb-rKKsntN?Ooy#!xN@yUM6PF`I&tp0Q0o>3q4Qf@QQ*%A()XweSV z$&1QYUP9%?Illp9<`*}j!v#NsVm|%A{Txy92#)o*g3;7=qAcgZGdAXMh0#NY)pvZ+x z;349{WGa0)VPH^75*0a)AeroX4s7D%3wV;6N~fQ3iX3)(xUZvRJ&ToG{FYwH%@qS+ zhhE_gcj(O#zmVujbPlH;SYO69E@T{j6He{{Y#4azS9m>dqTmvj04_dItVUaW1N1j# znVR3yn4^3)E-*JffAK=+Fb55S-3Rl}Wi5sa(fp70p?chhkMa4*o$wqf>c3+00bxM{ z3IpdckmHL(etU_hEDE;y10V8gl4)##>xQKUV zKsO09N0UvuBG;b1dm*!}f&*o`E3?%= zhkW8Bh}>$$>&-xJMnOM`)LR++0t^)RFi5=)MbQa&U6<|Y-sSs}rhDgRSs5iTKcU5`D(r7n=%M9C4s zWj08Io3`>L*kGT?I1eu9@sG9zbRd_7P4!$`W1zwxK%#dY9MlX%RtBa9h&dW3bP@9n z)HYv%(&SyDZmoV48@mKp&kxc*a3Y4~_!=)@9IgVc6A`?9#EYk=C68*&-Ff*^1-JS5 z&rw(7OCYDmo*GiziowM!yIy(FXZ{>6j*berx(yrrDJp1f`7`_i+!~t0*KN=rVDLY( zeruG~O>*xNd`;-C1OC&}Botq!F0E^8LwJw=o?YKnof;RnR7y&UloIr8zyP-aJ9%9Y zkvP-+z$DyeK>Z}D075zjXylqd2d!;lOiV~1;RN0q63r{NHniTAkebQR71}>7sa0{B zL?*-3711h88;?Y{l(K5bf`fO*haxbt)J})vGoAy}0eg z_T)#9GmyPyChlyFRz3WM8JVXFF9(a9PprcAT7lEo-`SG}{nceyw#cPsS=k>g&z?1g zn+_w=3=r*(si>?gLnA=$pfN`)%<)LbnU-sTg@c0uqTv3^vj*mBp&3oVK|#cut!ZGe zO%%kiKk@j&)7HEuQY9UM2J*yf=?h-{_k~S(Tyn7=xf}rD`WD_D#Pg@bPoK=O!#vW` zhURKYN;J?3$wfkv%`HZMc6hU4z5@*|hyoEj%XMM=OB<|0CLmY9Chi1CSU18R6>^tM zRIG-flbq7w-?g5gNr<|OUlGAYjh{j?E55cP5rfho3jjJMfa5!EgCIo>wn{f14PKl8 z=X8UtrQjn>Yd&IzXcz-u7|n1va*%eA78ntB!Vl)M_RwaCbllMq;p5aa@qZ;O{Nl*% z80ad9umKa9|2M52WPBHgo<=`w4J?%Ja!k3$wNR&U0fGtO)?y2>cq=36de%1`QbsyK z8#e}7GBoQ=JK~+&6SN-=ZW-?TTFc4#akv0aM)Vlm!$B0Fyt<<&yfZ->GJyLeBfMIg zns0{-a2$y~mWeCTrnk)TRc%Wx!MN)ZT$Pli|8hwwaw4Im(DBvo+cc;G&`s_YAjWpn zkLv`4gv>D3F$KfKpilVPaj-!4#JGZ~LZxb5J-sXp!xFQnLbqG(zYJE^k0@}4=uNL2 zU$!e=a+>*63OkFh-92FW6)|~ zqO30%;y=cOeh+S#xenSdiixQy3te_EqWd7IJX13>^pS5r6%g4T2O2l%cE3MSvF)f9 zhwJ<6j_4zS?hkr+6tz1OzyJlHzvx$Yn5{(9lY!5l`^fcW(14mheSd?3h^zBxLDcPg z#N+K`9^gu223r-Rq{u>5zq$dhn*K6$YHwbtoIy|dw>JB`DHX>d&Ot;22-ipL3wu(? z#WbYm!aJvb#>Vj=ZD6;$LR-EntX2ca z26shy!CnyY#^c0S^=}&JEHS0on$q#mDQQyNd+mEPDPHKPFXLX@=GNA|`Q4c5A)`OU z5fAR{j+wl?~V^CI5vCmFkd%~sQYrJ@KnZ=psyZBb9@gr(W+5bPf-UF`Z{r&%U z94qUjl#Ec4RVaIfgk+XbnN3?rMn*=_k`gL}$S8%P$coaSh@`SIq9_SbGV;4$#`&J# z_xJyQZr|_c_BkARzhAHCxUR>#4Aum_CJgWI1J}EeMUax2xs9^gW`MrGKd@#YYSe~- z>GpkFjSEOw{$4mwU(Z|s4LoJq9G#ijU1C@84 z@2Glnj}oQQeCEt2+L^un>drAGUj%kLdHFQM{!yT!+TFYRt)dy)J;<>&Hd3e0@2ukr zZdffp%IRb_b!z&XCkgvsQ}CZ2yhiHIyLSWP*M0B*(BE?hiD-JP5XW!#kym#gy-UX$ zDcXJCG4)>8$~TYf-K&><^_P-vlY7j#uzYLt-U}?YbgWj+GUGh4m2UxCrbptpQnS3j zx`UEuz@rCoLhHrG#x8K}qN~pZ9BT89OES+l`^2Di--4>Rt#*H#E-hHVo;~TyGnPLC zKJz(z*gl}m7+uR4H}J4o1GF{5LO_aU^VpkDpZ-|;M+yk2{-Q;T#;~3qE>Y0q7hi7F6Qgs&;7vBJ2FJuGoy>E8z+SP#$-RN>%`l2Jm6PB(l zH9=aPRPbI+T|GqG^(~D{X;A4n2$O=MqTClDZ6Q|dAz1J8wyp2L*ao4>=}sLz_HrB~ zQV&TU4G0Oj$qP3Yz9@*D&?jfgQ9OOm%04zd^_+dyfcP1Z0jJdWC}v$3Uo#);PEO9E4`q|=?82tS z04$xj-=z_7b#QUXy=cX+>efH3g%F&jV!OacU^yOQm@=(rPSl*Uc zt9kktcJ5Sh!hs#vF0KI`#%!RM+&5c7z-#RXI9$l_m)q$@2W{;m_m5BIFIH>QX8-aZ z8oe}L{Gi6@4(I?XHa6f#9B-jHSL+c<*wS-ZS@GV*Cr6JOWz9X(+}Zh4pUal|J$u^G z@deQ}Puy@RB<>hg{t`l^;-LiDnWdlKE5)Ivt6#H9x4r$0T)IplFr^$ zUk-(ZUE_c0gCQ&!+1~9;*71J2R4)$~jP1pKme)C8(NudUwawN;YOyN;M9>acQ*iMBL6aPU_CmxdQ0( zp0m$?3GY^{2Z-RFF79jAPr5~E(GYm~>+$fVj6)KAFt?v!4U8NAgKqnMTxJF10Ye~& z3YVYI;{{=ffH1Qt>wzOLEqRRn{VAH`5vZPD_(iTg_sh|=r0Rpczh2`ln;`c!Nn}B) zWUnzjbvbG8)F!wUM!h+Q+(0s0fh&sa+!QSZf<@B3g@5%Kicrl0+844tu5ma0glS7*mK>i%_K6gX6OT6eDCb4i@1MZ&sEc}~?p1=6o6Ymb>l>MTXC zP%t5)^nu$4wFx=loQ zM1&1(ha?Y^uWo6ar)_Q?NYrwZ-)%u7Fixd~N#J~7QqqR-39bk=%3CW4^EwRX$-f~{ zayB-aC{~05zY|Ablz;;7i0YXIF{3}uq@G5M3fCZ@pXc`-GaQjs+t+t9 z`X_YZyC0R&u%calRQ$$mnKp!}L{mI3C}^Uh;tsIydA66nej*~YD=(Ld+XQlG)SxFI zC@6J*sLH1l(n|7C;S>E`wBx43A5hl-d&i{(@u~(69C(WFjg{}T-#9&9iF7-{ehP_B zGQvNk{>ei!9?dcGUmE=)GLyVh)_?N@?5a2DYq+h&OHE~_3-x@>x3VPnA9%Hu1Zci! z8M*M-v3xU8Zi%b}B0-sQZO6(1g1D0yA=(rc3Wb9ty*Ae_T}e^27zhrussIr49N)nE zM1?+HHmbYsSiSp#oO$=qFbZWXge~!1V`rF3Oc%ln6Xi+k9n$YlTeOaOFDPCZli%}1jV@neEd!0rt zw07z&kgdpRj^DH~N41B~KmWz}pW7b#dB*X2p1pnBHSX{MN=ym4=9*ST!!0ZE6pqfu zsOnT!Kl9}ABhBnW5lR@>Cii8!BZhy96GB3Yj#h)$wc;RC`l_(N2|%$sYIvb1*w2u9 z#z#Ay2}EK;jLf^8+qZ8N?0xOTyRB$&fIX-(46bl4*5v^=Z?Em4H@&P1zHPvzd>m%zewsed8QpzovU znHswvDImdBsyHLpbIa)H>IxJByMKI`YG35kl6p+R+!om=rMaBCAWiM}WtTVukP>-_)DUlQXg$IVQx^H0wSVp=c5@(CwPNF<>`vB)>FRqNx#L z%0X&2aboS-6=09X7o!Lq6m7z}V+YXkDlI$fhqMmlH0H*AeH7&4apg(D!mc5On1!s=dBiLr-5b0(sp$}}s-TLz7%VQ@`Hq+_Wwd)A#R#u%UNP?GFeX3gF>LL9Q zn=UA?Tl=}BSABl>On?)*TS&w8Jmyi~`?@I}>`2xAPL@6Gg3Z)9uZfb@J@WT@68U99 z1x}Y6{k1iW3@J0XD{8R7flylyUZ?Xuj*DwEG0to;2?4tLVmBN^cYXcsU*aDg&kv+w zo)h!3>BD0a9=<;l`}4p7$dwJINl2VsB!`QL4IW#=pc^B?kZT(jeUe=yfdPH#Nmjox zA3EGQ4iw-i`VN(kO%s-v%FUbS+kOhIEiU2>JPq(AJ)3Lw@aXz{nWAK9+y%w6bi{a5 z9<p2~-cRV~ilrWo()$b-xo-D>lv_7xv zEAwy;K6qfYApc@>9KFM*PY+4!3%Sj$OC=D#Q&mG9^r*EU&L9j(5$R52)JF|Let`Z^ z5(e-4Zp6_#3qXr!8kF~*=4VrCK`7)DK%bS#_TIC5hU;j2aEA0_WeF~c*${Yk z3L%UHSWLZrXgV<#G>e$sN6^Mv(m;&0g=N7QFDlhH7^{JCg#Z$-^^ z|E&bJ=amm!g|0*#UX6ifC%8+$79>JW&>`$TuT2z*i`4UV~o!4p6?{Xvk*SK zc@!V8^Pgq)UN@BDPz(<*J{_j|m!N7q;nyM0Jv1Xup4@^*3ckFZK2bD%TVe9zmH3J#=FUG($uxS-Iza{W4rFt?5;fIw_vm^9b=Vyb~=P*7G@ zM#W&*bUNrK!vS9-?>ncop*m5q@@zq=6EqJW|~i5?KcN*nimE;r|;U zGaKC7I`CZY*(V`*GeQP51Ace~_Xj#?sskgQOg&_@E0d{8+>1TOx6m*uWWP(?0+5q} zZW*D6xAyi+nruDj==5dFJN)_p#<{=`lGZS}hZc$BT>i9yfe#EAz#s`m>=18VNidSG z0{-U6#`7Cvh>L+F28QjJ_2A7U$L~ZXKj(oAR^B4V+Y37^Y^Bu zEdY$sOfH8authTg^Jd$=naVxnZ9E0jA!`g~zL>nWH;|D?0VUX-1OCC8lK{EszO5-k z5v#f1R^t?51^_m=4cMMzU-u3B&a%DA9u#d?bim>w#QLaoWh+2+q;YZgk3-yJgC@%` z9rz79$Y$PD`kB~f8gAbLDT#p6wvanDbxsvGgGf)%`=<|5{;s0+^YIw{m3-~mDfOWQ zv9QW*Ev)~Pve6)0eX~@qFrC9rJzEy&UaVQW6PsM5n8nJf50B5(?RI46bs!_|stYRTEVRw+1TU zdK%lSSUu9S0DxcBNBf5UERpRxdCTE_e~z~8(8h7?&fH+fC97tql6%I#z{58i8gj;q zTMv91oBdYeN<4ie3R>s~SWQ|QSj~E?DR`KE(K^%~p6MFrP&jAFYei8pBG7A~OI&Kx z;C6-&jvX7vIjU&rQL`W4{$Z0aLkfw3t^b*QYwu9Rg7$3 zsUbc>wBC|nVInRQc`&BP++w!!fi8c3E~+ol0)rJVxX{=zER>xIBu`U#JTI=>f2tPa zksb@k8uA?TywCg`9dx)cJ3Ndfm{D>(gg#VvSDgHfH;y~MY5z>3XEaI6=u|rFj?v+t zo8PUY7jqtHTnhl~9R}i@I;+m{pgP4W*5hVS`CRHiSjY7tHg~%n)pZ_Whmy^RSGP6h&Rl6Y-1+C5G;HdQOoa=_ z&FeAjjeMx47ck%-0Hpu?W6Bi2^oW}#Yu64EBN}n#9B(7+1fdaIC*wctm##6?dS6_b zjS5`Co0|8*`_Fp%^bWJmo(c+=8hE5|I@-;g>>U^$eMxNIiR#&R0Y{9^;EJM zTZvlVsP?DE;0BEl?Jh`d8#X;F_fis6zcC< z2H=((Ip;qAO)zbe*};k^TI<2zKPsau)6z$~T8F=fbzw^q31V^Em&Nah;92we*%tMs zHd(&!zHRp{g>hE?a^)0F0d=<7!@;qxzm9dcGnT)>I%pJ}okQ&&(Z~y~0s289HusVU za#pV{02I}wr3!)RnBaV#M&kfQU=VunU{=obqV>NYkY8_BrVWr_ zW(~zEvq_We0mOpYh;g zM-cM4-c>!Clf&*r6h@q_Qa?RN=dY`;JX@^BfuY^8qemwl9lHTX{KRE?W&K}Zey#}Up+~1J)J55pfGBS`|fr4k+LT!s5_O={L^2(wr;iO z*l6#vb=CJS=pj(l%|Bh@5wLGx*E`iOKYasX)|U?1cJ}NJAJ$y{@I1MJ1330ggC{KW zn+BO#BZ}&Lz)#-Zzo?ilFe}fw_n+ccBMKR0;z}2n-c_6L(Q(H!toNawrAo_|=^x+R zpZKQS*3Rx47{X4_C*=o6@OJlO^w#b3T$;1lg$!Oy%vxaxQ-fG6-)`uni4z0fS60pj zmVnW-iwu9VAvb~YUU;d^sReqx`UN8$NM>l`?}L17LF&9_5^XWU(z0r6@^i|I-WO0P zIs~M0df5Qu1kvW|a}$kOx>SGSBb~5e%Rxp!NuoKpI#x*ZrkhJ zll${@PNr0U{X|_h#mK;J)kN!yB#K?9o~KJo6Ccp?g@>!YRnrfSy?o^I<&$*a4xl(n zDkoRG$-DEdn@7Xj@f+6MfB3M$AV;doz?4Pdzc285bNdlGbHbjDRh=WwODfYnr9noUwK_%osB{#+Y%qmo z&f5o7NNU{lEv>9#wjUaV{Z!G3_|if;Q3qg*Vep-JgJ`fpPMwN z1T+emGGC}&c;pO#O?ZC01BZuy%1uC#u7*QdTSH^$qBa9Lh4i_k4f}}|BhYq5Pl#I^ z*F{8NXRslI`Gi-`lchYH?BJ_3oFk@83GC-wyd$kz%Fi0J1n`R*xEo!!x+C6$qeDN8GMfq#l3JNo&wNHL-8}Pqdl6E*K z74+x-`sV%c!{_z+Rzr;*3LV0!>&K7ROA@i;Ku6fYF}AjcZo2>o*z-x$YGlA0SeT5~ zBAn!g7`xwgdzz0mhb7QRlceN69TDE2s1D>c+-*U8g2+ZR#;6OMk$O zkrGrCJ@_~aug`s(LxA(g)V|%I!)p#mQl~}_l+~WT33Kmi``exh`=kc>q z$B)my7nikW-JS=5AtBRGPg#5tQ-$3gYNAme*QVDDX_+SCFSmUK=;C9Y1Mi!({Z%&k zImmfU(%qGjZPvO`7W%&zY7?fB0l=Mh?0BU+VxlyyxYHGM2VetU$58021vs@3NQ6d5 zH=+OOcVztju4O@CwJBSp0p>8yT5}p|77%#6o-RX7SB!Kx<>z;Xr!|O7;Ce`9B%}lH zo6JZF__74<(ycXuw}xou%?A5wGB~!`g-290fGJ}a9m28@vj&kC&~4osas?}?Ke>P3 z(#{gvo1}TI2bbG(22H&b<>h5^JT9QH{9*PN2v303dHR0`rmI-)3JH1q;!BJilj4UB zP33pNcjwDiZ+3gTSGkw z!`6D>%CSR#TzhDUCB*;LSkFy`6CM{I0ahER5Ys-e ztKwdLF5P)%-^>~|`#aRQot?d4`2eIr{`LU16HM1xe;stUiK`mbhQsLd4@O%bpsrF{n2Y}f_QuGribLOO**D)K zhcg|gdR!PS_w3REm-{YT)ONM>?ZIEOX+LHY$?SQ4Rmwb4?C6EB#KGRbSta=Ok^{3 zaXEiRGnCx`C!;bTXV=9A3%YDAIy=bTPqlv^Kbah-(XpfPyOsGDSIL96x^SV@pT5tq zMhyWAaBd>o(poMrj0%x#kR49?$>p%ao~53I_6(5;w$G2ZXumTgWGnGhe`B5oY97kx zq0rF7VIyOI@d@twqNnhEkD2*`ruSwF$cT3Z<%YnHH{&h{J1QK*)dFGUIY3+M4Ty|W zokqr%4;Od+)_A{-4{!O7av`~*$fZ~rvP z#2{`hS0W)(wz()&MA*EZBcu8s9zKE(@?>cs=Js*7$`aB_3^WonB#=M5@F^wt#+uJuJIoU9>%PbRaG9_8 z>b>j3Rf<`yEcdru=0F2sxa~Lu6h+45vTc9*nPrA(CG}ty1R3VbWD&32ANEqNnkT zJO%@|hr)Vv#8&w|=;C5LLEw$i-%nMoF_3Y5F2lQ+F8F_rck{4g`6#+~WjVKo0W#c1 z3Y(<~(~m6owOqFRd381HSFDR`cD4J@GuUq&JE#ZgK38a@jehEenc);U^{lVUiW?SS zhx|norcKk)uK=bNac5M1CD)pa(xn>`M#IK&;R#q&GCAC|OKYy@ys)9|i!$iF>NIX0 z?rverZBo(9(>vXHFg4552bJ!@=xF~^wWt`eW0UPxs#a<>bt+LLpJ#D9ZA`s6R=;y2 zKI7wtS=#ANe}7my&MSBDUWt?CynC>Fy6O1ejeLJ^#M^w_#^8r4Qx#jlNMRHd4Ewa- ziSi|cS5boLt$a6&CUe*v(Xm5M&b!z068;#Tay>pOBH0zEOL9=da6O!JF4;9Jn70B; zY_(=u)>8Uk3kJic?Tm6u^CH1sph9Y7WBU(dhG*w&Ecqo4alLBG>l4`a&53TEBTnxb z`oPY4(U2L%0GF`BwYO#N?YD_?CC*_=_QYSPrQa=0dKxG4*x%jC#(bvhci#n}b@p>mm@^l> zFpY7xe&e)Yq4^60^+k$(WqB+2FaVB^&`+%?{B#a$sC(*UHcA@}5MsFPNzbA&PX8Vl z9rT#?%mlgyK(|ffO}wquWJ)?YjES5UmL_@q@DMhmf2~sk$Yv-+FDD|ylbTp{<4Xa% z>OQFCq!V%~^tjfO7YS1?&Yd?e?iHVJUDeBG0)6!Ey{oiinDTvM^8^wEI%|bcWkIT` zG31kGdUa*OkJwcSj5u0UZeaYiy{rOP@Hh9?=qh4eX8z9tenqb>@l>4fX+hA+(zg;B zK4kQ0Z|<7od|66IW~M1gMm1vAt9gG;%BUw?b5cFPWh#{>02z=tBnV>rTa4BEo2KMy z!HWD8 zNo-71Z*np!YAE@@J`g_&x-u(`%YEwiPA5ohaR&;O!LmpQd!CN%i|aiY-B8{dm=oHN@&&-!a_&PIf2x)i7G z+QVwC7rhP+wCVpqekd1ucKnz@@|EQY%S~X@$uB7XRzN7@c z#+_-mOX8!Od`qCt6o@of{rG8@y9w>V8)5Ay2sDlCmWJzR^z-c5wp1%Cx#0e~xOYdH zvj{4U-k6L20e5K38o&kk-8pwIV;#mF=SjEAvE?y+?;p54ujI=$yH(M(b(L8!|y7t3Ketl3yZ3ZZ! z-^T~&#>SZT#zj&|8ETjI0m#eiV)Grlh!?7{9yA7<#g8_tE7et#1JWE;qV zmXJuo?RM?)ggHWh!!^OfNVi>c)$(=qr9vu=UxjBaP)pz$<58ooGDFR-5CNC;9+aJ@Ek7zv?!_HF zobnqrGfbvMnQbn!q+zGSiC@!SQ}r@%?2LwD&Jk~-1?Lh~Hc~X~ z0M)9=P3%+8WPSqhy9_<{RoY%S0=?J@`QbRYTt=>nhkxDQ)LmCqk_!O zZta`FQ}+^fY+0zs$^OZKcoYfJFPX+aU3y50Sc4&jl@S+IqG(z7t#94eyN?2C%AngC>tW%QsMS9i z%mBcL%MEOvfPgT>-6y4xVmy%~MPZULm>jxZ@pv~}mw2W`7=o@$yT_BLseMF$ijI5x z>r#`n!6LZ2eqDicaV0Z~05H3wa>{v)nu5Mj- zJ%8;XL?<$vfrtceNAb;D3aqU7ZBGt<0y;AD~s?NX}qM<$Fw z%OWA7{FGeZ=*K-?avh3v^14eTdWGrrr#lTsJA`h1f1U5Qj*X@|I$WWysCc_preXRSQciPzNa*04>}t{wp1dmi z3y)bL1y|X?6xZtVHaVr_tz{xe_gMAqvz{_4DYOWB)S+e%^MTJ0(+1qnNlWukXw=AF zz5&uT5zJ>$&8hK|90;n*V5M4YyALfO>VM!@^Uvk0p;L0!K1P_BUkXQNadrTsZ8r7j zxvTT#-g91yFp#b;yhuk=^ZDB4!DIiB8pa{yemlK;Iy8k~kWXXxl9H&brk2Jmo)d>6 z8Zz6F+i71F;nH^bSE@dL?k-t=r%zc;nv{$=s0U70Yj$plPTU$M3un+$1j7!*JM9b% z?12u@hm@%j1Io-Gg5C5f%*TE*KhuI%(FYUMq0rE)UmiiH1ja9YSwB~Al(MP0>EjzW zyxvz-IB-Po>3MQUTfhFd00ed~`*CwRJ)3fyHkoUf1?odPTJobMjf(@l^cZAwn<{ku zjn)47XImZDZUipr(^T#(QKSCz2@iigpt2v;W=_H&BB!?x2=w+IU20IgdM{TGc;6Af zqA8mG-DwPcC^1VekJ#EG8E$94^9A4qeF|#3$G09m+S?Dk3m#RS-17Vh5nmo0h-E}V zfXfL0(I9TX%b8vO#ZOnA)b0rrRqwG1g2iza z&(PV#4@?X;R-ZV2{I<&-evAj$1lqrM;Kytbk_-;q7R&a6i1uLAa@nJ^u*BuaL8NGE z^xy}_NTN&fs++0wctM=DISZ3*^iHEEaB;#nsz5@iI(FFfkVQ|zIUV)^_tZRm#4duchAGjuXzlc6~#I8jZoEgFskypE(TXq-(IM{P41MWms<}`8Q z=+UDk4H2!s`{~n8m-=M1cN^U>=>W^ctg`-`jk*1{{kw?f`pGy71_selN0$HAh0|r1%cykUg;M4GE&&Fe{fT%0Zx*PG}O|oFlaX-(m|f&e;|wCO5wB`?zjQ z;I>~Vp<#<_XkQ>K7#_Mkercl`qHqFk!Q86Aa&D!i^#SZBSt8~s`_nQw58zpSHkn66 z;hz*^I=kAUfecAL$HKw5i>!cN^e+zYRs&ZmQnn|7=!@>=aI@^co+1p`@ns+}PM=l> zDH>YsrqT+}BsX=Bol5h6G5W3gfbP;CNd)+quN&z*L}P+fd;eKQMC0A99yR{gD$$06(!Q9UkHd^t@BunfvTkGqQif+F_<;vyMEYwv$N3r>)7RdA!R42pn+wd~- zUqYz9Vr&^&z{aTfn6+J$Q7AEazDdUbEONj4+*ePnHC zXd1F#o&!;sPjEaelW+)OBa?-=AzMzp&QqCo#;_pcC{C=-iTH)DS!<#$+e>LZi=xZS zcK_N6%ZW|1|GK^Nw?xHHdpY$APl_LrotgWJ84tviIYnufo4t;9&H6ExD$^I>C z&9|^)igZZMaaW#|SJi9S5VNlP_JAgnPLX5f!>mY@Dlht*Y(lTrfD$-%f6M00MPtfX zp{LzdG<2U(B%jC*xW`vo_^HDh^sJ4T;P4<56xKgDSYiJBk|TNFZU6KIhP$UhHH&!$ zJ?O=?Une_UMotTFx4rXorA2i3Nlf0UC>QY^i07l)&(|Ai4h7toN$gaIX&HNhgRNQ5 z5|dsR1F@?>Ox%lFN~22i5~@FS!yMrhPF9yVpl!*ygm1 z!8|wg#DdXswH(e~;1+_TCA&y~w~?dHA=hXOqf5r*{@4T5BQjc`^RWPjn*?eXuKvvE z4MQ~0BR$DzdaY}9#yH}@2{H_@7W8_pw{qH0c4R_}gcA-cy|Mjbdj%reRdIQdB z|Kj*@_2%}+Fkn4B{%A*9gDDT9&2LIp4Jkv$TXkn%zIeTC)zH$Jze>ot8q`kjPP%>{ z9iGae=|(smiJi9@35qW)cikd}SfCCc%Fzxba}28tt)LJ4?9|)&=gu#^ z{1P~w>p&FLsv*J%u-P-2OT@ni_E zuGE5~%5TSxY#qld=u{de&En!vtnY4CAi{1D7Jga$FLbu+AaxG1lxO`@R(H|Wb&rnL z6Gqs1$K(QzUFpDTh^Jfk{DFN$0dYl3Q=(tn8F3~N8IP!Z>lcR&7a#^GDD1%{E?^sI zqR7gokaUxZ%F4P;oFJL7Dy9?a*7zf<^HX)pEOJs09R+o-f^aSG(&|3cv$;!lZ>5EU z?P;Rkf7un8%I@M7!|VhLN#(|2(->drddLlqyhryG2G1=(B6pt=r{I(4QVItadQjNx4m0xR-7| zDr4g=ujwbmKUcuEP3AYp6HnGh`@l3}MJFB^bCo2$zmS*tnsph6qmXBc zisf2=j-JIbTMX5s$+!_7#VcujBqE%{_nxmb?lh~PUj&TrD}ujItLe2w=ZoCTc&jT# z&F8ll%9^g4bKbPmFHk}ECifc?Xm2?;j29wQ$}XU-zrOv@oWrG^mmh(vqai|Hv0}s= z>fKTb3XW*hz}ql=(2EuNkVVjZH`ut9o7)c@1|Clc$q8%lsIhoim|+`O1g zLc;JaOQ0xMT!7VetdJ7lERk`owA;BUE~mK(B7cY`I4os4(^)}TAqIxG-uH)?IMY+! z5f}F@XCD^`aB;?BakUE>%tTX(&3p4^L2y4>nxB^3K8~A#mku7!Tz5qcqxO^zphtY!3G+BvDx|^yLl5;) z+xB|IZ_(nJ?!1UpFsXQ74GbpaZb)!P89=&gY-^&CT9W*m_MrR=#|Xm5Yiwb%nIk;X z!h)H<)dZAv3*cuAv!%!GcEcvf$?sji*e$z&w%?7Vnr#7gVesWuyYtpPHQbyy#bhE# zZD$+;i0Z5?YdhDd@$YllfH>`%bFEIG&k{dRpOO8vbq-ctDO1@Gb`LI5F3E@*F+?FB z+@r5Qw~pH8p-2rGawuI~lBh0Hso@)r7LV z=yo#ijX0Oi$CR^-xl_4b^rNm(6L&}G&X083L2}gtHtcgQukD?V&7U_M^u zzGu~Yg%vWlf-=#Tr-zc;Z#P1MO}M3iA|yA|mn@y7{0#;0jrs|*fsgfwL;A)A(W*W6 zFjdJ}BkvX+Mpz1vk#q!b%fW~2va1gdcllbO3yZx8X$ef-kqT5T=PL9NP*6hbx}O6z zP+aU9GXD-rT`CUhfx1-LGJ%CBBBQRdF01lgw+03Wd-BF@@5k78UX^4>Xd-*52?asj z&)gpVco13P6Zm7jetccREH(AezW7 z-3CDOoTsE;4zNgZyAho^)#}{)=#@iOUb6o+8#oIgLSM%-KS5Tl36To z-n{8+G6lC@#1ZZn`f^g4WRBVrq?5wVQO#eW`;GU_ZA&*fT)bS^ktoJPxfo@h5%=k< z6jRZ)^JT>0O@MFb9=YUyQE1pAf^UTvv8OxNCgTQMX!_UVtt5j6p7S-IPk5fhH?hh4 z-IReMoV(8nz14Suypuf#ppEoAWoZ8_MIgAmi>rDte#m0V{fb{sc1co}S02Jp4lg?Q z$wzM6lRwPGFJ7Uai@X+%mhjT>xAuix-}OQ#9P8Z7m}+eF$(ac$cz68v?epESqbX4# zPub#RycG4{o#^}~uL<2Hm#d6}Cpy!c5^pI6HN)LeD|Ee2@~JjURs@pI$xWMNjlm{- zZ^qVj&k}1RdcPj4zAZJ0)gkknbNXnH9S-6_2bRn|&~&-aW*5QlqtQfA$I$3A|^YGCgD? zm}mB+eqhby75Tl6uKx0AKG%huUTnRk39DA4=~2ad-B%c40-53ZZnv>P{++~&(on2t z5ty8t%%C)I@uD~5Uc337hucBJQkyqTn}^}^#G{8qY0hFLJT0%1ii4Y260y)*3~kcw zD=*(0jlyu1T~A|_>br|gg~WdQLJ_6WzeX~K1R}FlSi1%I$Yq8E%j)#H%*ODebO~aF zUTeoAX(H1`R&*D_QlyRdce5{O1qAqQ9__(sl zJ(W&9dMJ~620EGqglQRgpf{Nt3NlKIy?lTs1R!Dq92w{D{2$XN8aqbh$Gav}&86B{ z*rpPUpe^+da+Q&&#Ap!(ipzN!+~^*6NyF9y)u@+6cg}JM1?H?Zvk{Re4N==lmId8H zlFRm-TeljcJfodyvl#p(XDvWQUFvC=uu02E*BK;m4e$OzTvzt~Qb)3?8*sG|J4@z5 zPX4m$GO0^xN43+BW7I&Sj(ly%$dN~{R~)a$`WL4n9j-+Y^#em(HzEn@*spojQFN|S zGqR6&2H$1;87){yEe#`g_*IExBcCoTV=srh3{z!inqAN}G!Efzd5=CwgG>~MTO>y^ zD$qM3-)*l~@!0SqsV~_SiY;4uW0M|HmX2&)Y}2^qI3y%Fmw~=l(WCF&)&G>J1(@8# z;6?L?%9oFf{KooiIel^N-MdLL8tnP=ns|IUW_m4I3Swo@B1UJQwVIqL$fqOwobFA+ z1{XGYe}{cux%vG-aoyP8xE7ZR#a{Z__VF|WdkP`Fb%Qs zxtC-LvMIIi?~jqj7tz}l4u1PW61XL!ACTbA@K&uP>mHMxJD=|KEs;b~q0=$~ZW($E zq-t{G!5l<@=Wq)wM5=dGg>|pj(}*zn)%Y_HOBp1@u8>?yZ+=KpV&cY4%a(>7{PLAH zwzX&$cnw4@57ANWGiNo$bl!spHmERVVGG{`P?iLCIMg%#Q$^`iL`HQvX3g5rsWr;y zOuZzzfZ|6Gt^LY@`)VpF8+y!Jwcq}|B!3Vs^%Q$CA5 z21Ox|GsCrcwp!mt4 z`5U3Rz7uS#q^wXCPx|gSSmj>Jc5Fxf zF;m}Z5f#4$Jv9UUrFW1}*C6A3DeEm>kXPu3@nMA2t+9o>!N4WscTTvaqmVQ=c?_NbP2WOZn!rM!wUiliG6LeZ5z{a$w}N z`0a}}hD(ZJ67iT84@cCHo?T*m#N9}zqp@`oE=uSDiQ8=pzrNDPph z6+k_F#;*PEU7$F@J1& zNoR(Zk~NS)WWto!M;5!K74b1S`j6{|HB(i+aVaV`*17cFD*zU=SM^h%dxZ5L`cOJ{ zs;Zfr9^UNP;lFjx6sKW1L_o#9DjH(>JAagom9q-co+V!wEN22oh4IAIxt^n8GvzjW zvZlOIRDI2`+81ch#MCE3^IH$^-`CL6s)bV6bZJcGh~dt?LEsW8``+;-(mowYqNKg7*Yga1Qz{A87FH|{qwP#CT2>`lbR2=>#0HGFq)?m^PEo!x2+Q0=jK4p}wEmlG9-e z>?^H7KjY8&tcOEX&Jgp0)VraYSz(aR!x1e!Kczc0$~?WqP|WDeH?1k>2x6D~s+F`q z#1|{_Tu56n0q)lLaNM%RS)>>_$``z*sk&0U0q7H-Q}#o*otkoA?Q(U?Wq0Gv>{UzawXtiinflTS1D^bayDhcEa9*C0q0WpwZ)&nKY-4 zp*h7-w;&EEeO7?a<;&FrW={R~U9v#r-=Lbi_3QFT%en8+dX zGklI7<;%d}J$riaW{UbBxv`oC^EALEpn31e%tI_8C!mNEwn~OOD8jcjsaFfm+$F@- zTQFHIZSAG%I~B8rP|jrF7fGknjJvhpk>mw!IJS~wW7}W2HzRx>f&Ek*&pEpy&nA1r zxy!s^m@sQ*K4L1JWMlHdfU9FM$^+)k)Z+e(C|@Gsg#d#xtB1R-lOCaT--fFMCeI|Y zpXKti(YpC@guYu^djvMrweYUc9_wa%$G5=cMv7}qIy9^=cNk1oyTii0pa;?U<*8W5 zNBXvsbGUA}x$>tUiv|`?9A7VdJhTUIW%BH8_BGTnsbRBUPx8iuRaXH*C*!MQIJ2A` zT=9|H^q6fyTM|vly6a4F{HN*R)t}$nI)Li}caFO>r5T-yKhYG{NPIJ#?LO>7+!!n` ziGyTS(IopeOa&4Rg0mfIF=UTKxwsCFzi^=kX|%Ek6-o4&GYf9tdj-7Y1GFH&dgS88y(Qg-FJjKm_AmW0k=(lI^2w{jqVp(J z33zeskj_{n)aAc}nC^SRHo}KJ?J{M+r&o72&6uxjIFD$A?f~}3Djm7l+sTg{q3OR^ zJy7vOAB?cGoC)*5iah2GOo~g`SDH>&6+mtPT^jrbA&mG-63;t7H@6h zKa&Sq@bcxSTV;Pk#?EsbQqS~Q;TfH3DvAv5Ela0}@NhlYw=p2rxq1rzQ<3tBVub3i zziXZQ2CQ_ox^?TOaF&f4H*Qg!3&RQ5UMg3k= zFSbhxq@xp0D=QK2ygt-n)Og3RL)}zE$GIy8PX<8gfO=j z%X*zhOJ4By?JXEleae@DFQexw(f;_5VD41;cKV4!JqLi#`OpHDREpVNSyAzT*`SX* zL(iQHszM`N^2UFGqhlsHaO`fygU_jMgIGHWPWLQ0lY@W=^--6+kng(LNYk2*GZj|D zACb`U%9=ayPxXLKn>KRt=3NgbPS^C8+;$PabM{!YK?ve*dD_96l8Zw6>~>|PN$(18 zwxpw#oH9^;>$M`J5xFP@glXm&!?e|%x^>$^Aq6l%xQ%WPnbPok0%EJMfK0XmMH|n% z_OG*-*l&(*0rbxZB0)9@n_1KUSpMo)-vUt6aG)dM>`sY=LB4bM@DDscW3BDGvhSLO z%eW7Qc|F6_7gRzGkzRJf_2k3QI(MIQ7w<`Gy|P+tXvT zRTM$-&yt&*FgG3>sVPZA&jStBL3(WwzqCD=U%MWTl#wFL=O4JTqY$A@UfAS2KZ{JS z?ehn;-nIpkW8%%5jaa)!ymdXMK_dJVabS7)e?%NdE&hLdP>ry|{KQ0LJsVj!noLm1 zPwn5guY4`8Dbf*6Y!?jEo>VM0vP5YD92Kvbb~E_~^DbpH-_D>3?axFW{DMqe5}L_J zI(3WKVEN?2xkA0}-0Ry@(!+%56u|^)uN*n7>w;KJdEJFEf)NsK!Oy!w$;g0pyFwXn zOP&vBLgTDU`>A-Z@__*OBg?sh>o#sh#NFZT0sc9nA4G*ER5mnO$*AM!5pu~$7pb4g zezaWnkRgATY2iI_M66J7> z7lxAbuuB_>vle|jb@Vc`ZGLsYIi*FCL3g~&?5}wU(`+FMWDYLkj2$~BygcJ`(B-Cz z6GtW?4>oHv5O&K<^Yb4((q2MgOY)WM8>!Mxf*eSA5(ptYDsmXNo^_+_E!U7=BT{(o zyBisBK;p^}4j5}&-PgvW%P};=3l7s#dd8K7Bhr60YkDdkLvmS@Q1Ww*)gNPG6+rC( ztpAj5R^JJo7XuE5pSIj;9*ADYRw94!g;*A)LX2=@oL}jwc(6OYA$89X8EJoc?bI^c z5R%uJUqL;tECn1DT)C#du>dBL0z*+Tl2h!`HkpnM&i3y9?EOQL28`-7X>xhDh$kSK z+yGDqnk8$XeBP5hAczzPfz?KmWu^as&x@SWh6+WL+d<^VN}m=H(W|TXQJV&)VMq(; zm*Lr_U0xIX$x**0JqY;A#>^sHD%ACQpz$%5Frtn-$>{Ji#|~q4fv%tc-=rb zE|8jknfl{LuO|olCv}&Uq*LTYLXD?q>T9u2Jtz)_$mNZLmfN z23{Dl2?EQ^PLy)d%V2EzM)C31SO}KYZuIOwTA3Wx+QKDp%<#$j8CNb^Hf)}uu~Rwj zUU?q^L7fb@5m1^dR z*pE9pY^AJcpnOlh5eqT?L{PY-sxjb4I$>lE%<`K!%gnGv8C{FKCTwmQd)cRe=#rwl z^StR>ZbLD}K?DEyHoVaY274*uc_LU-zy}snkmcN}^TTe=9E;UU^Wpq~<4ufBjPIfo zm(em_UNQ=YG%bzX<#1}Ext9c3tF_t*g%izBMnuqR_L0<^Tal8*2=^oNB_N>FO%1ai zK#@rlQsnS6RNFFF8fc@iEjiSdb1c7IAPi&{hT*)^v;QgCKJE8Bj;mKUY+7b?A2`sR zFZ;ld5y_#bqNh&Hz5GmlkV{Y9``R}*Tj-=PY*mJxU@5+yL25t~4l7BM>T6v2LmUU# zK~Wb*b{Wp`c*^mKfv{Z=!HQXn!BRMDxjkx0(3wkux9gXp`h8utnwU?weW;E6S_Zz# zMqRtV&$#lA5k)Uv%mQv=g!Yc$9t@r3JeR3sL-n&BaMcWLt2jhU>3T-2(vrmJfjsf0XQ2V%IMLKQ}OXeKG6IEpeXY>bC&~!p!brn4_Ztg zzFL>Qoiw~Y{US(@y-<1jVVY@KQPCFEJ)H)%)PQ68)AMd?Lj&|pqjGE}{h}{4d=hce z@VBAI^Aw5@n;@bSke1y++Ms{zy;gfbGG&sH2=xdG%(E#gKdcoo(|o+K@fEI0OUISH zVGiFsz7V)ByvaDdhMQ=zY!IvIk4~qneE)dGlV^JzFVA&e*rwjx@Hv)i3Q$k}(d$g9 zPu>4F(5MdHTPbX<-~iYWQ{`^^Q0@Wm|&jbiSvw$?wPnC$r^%y(_B$UzbM#Z`gs9aWl`PgaQ*U~<05xJFgRMTUp-<D^LH^$qQ)N@P{ww)D+-1oH5Xia)UWsZy5DotV!@0(R}%Oh#&b zlp@e{Q;goS_}J4g+p5p?5zgQj7lvFWGCA=)V2o5#R2T5}%p07-J~mIHZIGdCdk3uW zb>7D{!@UJNACRce4fJng`hNpvopdlyFVvSXc;iH^mjbU#Zr8){uq%YhT?Ctv{%riPdHT5NMht z#ZA0?O3KQXGn-{Iv!J)EPLve2fP&#yY9DUzddOw?Cr~a??+clf@dyF1T+Q<;4b595 zb;mgmDs?uaGi??%eIp3NI%{9duz{8VN5V__&d= z7OI)2a8&zC*!{jpf@EME{=4w^VAc|(!o19aj-2bQ&*;op#j!&S!zsoIA>+7_L1vyU z<-4dP>%O)+iy23gM@TOwW%lvncOTfYK%nnU{DN5$sbcHHoQ~$VfC@ZFP0Ge){e^5DxI!n>W*@8XcXaxOZa6K^K4$ zCg^!_l!h;%EdnkOf50I-x1RZQG*1f)HzSe?Uqa5^H)N7({g-td2{+&zYXANbBcwKh zsGt`9Ro`G@o_FZ*Pf*^(guQFX=>%5wB0ncD?_7m@H6|$xlt-?Fxt$r)E4l2zfwnnS z&yu!ax^IeD)PMDUkSWwob_;DuH~Sk5aYVBc1&y%S&g8(Bt_a~7pt;G}8TEky6>bOz z5&zu5kCT^|cLfk{MrH56F?DkA_>ijNdNg@ScBiL>qRh z$V7s6_~po8W6|dSWbR&kUrjMAJV(K=7Ja0z5gW&a=pDQGpHHG&w^V+2iNx4zYs(D5 zIk)FWoJVLDDuKP|7FqAJkTR*EVbog5vlbUd8Y92B_Z9<^h~}|J4`urK zdD#)}33r)vjFCjLq47-1Kx0apMF&3`4L#Q_f=GC4_&FkL16v??H!?SG3Y8wOFv3`f zL6F0dHa6&)AgWjiJQa;rhwR@+6akb7eTT-$vZ%wDp!M`cF46am5or7pjEL3?u;;}C zk?C{1Ny|y8!>2#=loc|gSC^y2^IUg1yoXmUB{F`Z;CS(`FoGTQPv40tIcWQnIrYf` zJ>mC;I_LpcJ8iL?1hH+nxwaOk&uE6`4kY^!&qD$@30!0&3LdWgXgEt0l3va; z(LG;-YB`j&gu0RUL+IHy zT4R|G&JSDo!M4faf)mGP@ML8iE)|$r0Xcmvp`%^)8++4dddjbZg9o%Yd+L@$TO~T|_u2Uv~YsPrrUWJo)k+&9HcYcS%L2 ztFsIYq6==x?XekER!Qc0o~}r|S(aVeb=7e5t0TE9=KhzC3|=vD#=RMBxVM9Xf@EMN z?{^EhAu5kB12AAfkbflIeeT>)&ex~!S7K^dPxmOlMQjN`Z{;lsoaJVwZVx3{+A;s) zPz($+I8%^raHAkdI6$aU;geq>??w`mU%x)XLvw0n`mGUD6FdMpV<+PVuS2eL2j#_K z`?e;@(@nqAW~M+BY4viLGslCI!j}A=X-1kxokS&uMvgLZ^wx(&6zb_U;r*f+3j1`x z{{78~Y*P|9h8(Y73?zi4$qP}}@8&-?q{)Ape@Z}Bh52GDLt|S&QMv26KX$C%!=n-; zVcDcs)aLCtLtu2xE?s~Q_J$yM#&1tc4cK$y#M=ShH~3;p6C7Ud#?&L~c8dKZvgsmn z2gN$hbw1ZAfP+FXFfP zI5Nki{Sjot2j|e>n0>$eqq+=%T*t_eG4l@`KFoRG{lMT;uS>=AtLHm7q&OQL?7w5C zc{5KVwz^k#%y5juwBfT@kvDt{>m7x>l6VO;^i$_eL+(kfbjX~0jp?yu2>|jj?$a~l zB2YD@ejO-)###O;g5FT?{4agf+2N{QZT{Qqr>(uK1qmv-$rRKOnacte819Y-zhRco zQx1K<7E{nk4rzOZE&P9qJM*|4^Y-s&7eclnLfNw~g~*a3QChCDq=jr-qQTb-!LS_fVbJd4A7h`5d3m z=h!u))i6%;3sgZ3#I^y9M&4FJdETQZhVyKJr7PyP)R z)OgwJ2598q3!Fu9S)z*iVl&^?1j7t573E_nFQfREX%pPkiIe-*wQWWHLLt6me0Pxm z5|}pIX=fdVJ|-((0K;Zi)`;A2kI5@V(YKxebb+;TDVKj`S=uJict%=(lO2R7C9Q$_KDx@W6wyY}pvsC$PM z4}@=LbBil0Kpq5IVgA;;?1RJFKQ0|_^Z!7a(wBdE--$t0Bc$=rec;2LIG%FsSW?eO z(y&0LeIuyb+-?ZwcI_AsGy?!6D2G}k(nNZS7X{q*1?1A=uP9;e}sXKNgu+r(LF56qt&$M9+@tJnuKOLT0eOTxj)eO{yeav1^}hEEe1m z=2KKUKB(gdcJAb7Zf)I=vNwAE3y3{|Jo^10ET|#Oywrfj@msqb;N&$Gv;tdJ0O0Ln zp3G~Cbo|JzQ>RY3lV9Ki+D@t+VCDoG0xwa)^4@$HD`a z2WB=uuxA`=t;I&l&RwnyT&B5~g=u&yeg0E+%!KLe0(2I>kFCC`0`Ii#GP#0=yK^v| zg*;OfP`rUp+UwfZstS~jiPKXJPV*t|omkuj+%I>=gD; zhLafo_*9jgInuk?L`CoJ-PcmPLR|E`EWYIQO>mmKJq`9d+7ht`keFZgJ#v*u*5taz zAz&8aGmMTA`XN_tK*nkZhg4)JT$efT;CY;ML{)HiIZZqcANzqpgYtZ6k0I93-l-B2 zLOqB4SA;G#8CP|i;wCIKFO%IrjH>P2;RK`eSg+r3jK#*Sd-gQqWI-{@-dy(T!7rR$ z-1DCIX{Gn@zcs|X!3;cDNM`aqp|K-B0_PJ@gE$qsve^RqYTM_sDd zupwK)wrAgCg1?43Y;mZ6j0GQ714wy}(M!;<;l6 zvU-I2B8;SLW zW!GlYg%V|w;d$mDZ|OVeSB=OlKHuKe@jRtx1n~8l^5WdfinNcfhxWL3cwUXqgReB~ z-0QCb%lTJ2NA6hjb$8&99nHggSO4S0^Q_x(_YT~AzIBpc|GmxcI{iMb-p=|v$L-bc zT)men;Av9Vzp5Q>@VMQo_k)M7t=|8}g+)I$?|=5&p0DA{cOUV6bn?aSlD2CB)aA`I zww}QG<4ZqtmAwfqAE`@Ok=ZTGQg7SUC0|-bdOu-$4DNLHNLq}{JG$&ysXyI7|N99# zcY!Hr!IcTZ+N`&(I%R3@;(l@67cE-UKFsp^_u6I;PG;NC~qGvqo4NPY;TAlZdR4I%OXaFtB7b<%kp zJpDfKUf-ftU?k~ag_Z|f8!G+q2>D@c8v&Wh7qICGJBlyROV;#)m2{=>eZ8A!I>-4_ z9t**W@pzc`9=d|lr%(66KMRG-`g@K4HiT!mnTI%RL-R`>j z98M>OXNG}4L9jEOHcd|h&#JVCgO5ZFC&+LKj!s`;*}jAPun~Lv<5GNJorSf;2>1L4 z4_ea=&Y>{cz0GzNX=DTWTxfojPrlxuuxS1^(^(b|Z$l{JD`4!hAvsXfvUQ4?W1+;PI^OZL(dcS!7yyKjQBJX(Wr;=UZX4Rx3d8y6kg%YvwP$101-@7`Hk8QYo@1Hbs6Tf zhvbm>WvfQ0OWM2i*1|tuvd}Xwk~dF$V52)M=b;C3OdbDDWhB#GH_eR^G&7|48ulUc zaFyV8**UTN6pGU}iva(lVo(e(;|Z{(Z@8KM@9a<(?(}-C)`7vB|E>T;p9U5)>F|tz z^h_tHk!wu%odu~ew-}>7P~I`SB8s_grIwe5SZ8@H^vpWXSTo+}*_nR*vkDh2FRH*6 zt6=Uo9XARKks0OXF%s`#rxO`>JtN~XSjLkVFJhASJ>p&D#b{^Kwb@*ieURInIdx+d zfuKa5-`0HLZwZD4%}B5u81a>NBxG1oRIJOf>zxOU1!xcQHcW~%C3>-M|pRSRC zTeiR=Fo6It)qCj$dm2sIZ!aJ@l;(iYVAV=^)NCB%h6uM{Z(ChmE!YP@9h3c*sP9cw z?=&K&N#31PE+?178iiQYx%OkeGZO-SWAkoW z4x?!o1)>C<6&eF26!EI@kUt*L{^`>Wkk>Ag-)nhcAj%Y=J>V&d4>-bckg#f?Bxp~( z;Yc*kUXXvX7St9oV+2O!Z!qv=aYJ#8m%Yj0!L87)+d8dym6CfjwWr4uZZbpE4S9KF zOM_K=D0bqV+p%PcHzLcRwZ~+#- zu%h(s?QKh$_DG+`I%1FJXJt7!}jzqoVvZ~C1napGx@cl86(Ps2(#j;>? zi>{kdn4W{1+9crlIv?PX(9Q4j(tL*VhkL%3$E{pr>ClCwO>0eno_5|()3^LcS`Fg= zf9~zx4>9G?VUMPE^6(&bDszGA98PYbv^%}s%IjU2?m)4dlObBvfGDE%)N^br#bs5f zMR+ReA&2>Al0%E8O>01g=o)5u?x7EOo`g^1B^GaQZY+0`5gW{Sriklc6wO&_#isVR z+{$M>GGbqC4PmYWe=?EXlIQ7kY%W0j?@%TnG^OT!*k*%6k<8){5}d>N+vYLVJk~%l z?;hx=53b_toE$|)M#h+xD^KTz$9##58V)SR^iAOuf1_IT%&=7pxMg%DlMBCwd}LV7 zx-=JW1j#)?|SU^Fc#C@2#l8gV`@v9*qlluD&}oIJuh+>*vCkNB5n5Wty1$^XrE zS(2ooJ})_Krx@m7p&z_``$X@2ey(__me?q~h)!2BGA25C(g%dS$wlCGF7J+Q&5jMB zNYe;Sm>0Am?5?x0j(uy@zm3^YDWxjygiHzVB@YN>i7Z4rSRy@ChRW=^)Ft4pV{j8S zvzXZ5>-ED{F#QtUVDps}ZeD8FwV8$n(pgH?d`!Z}is?4cJtRKaE9}v9b(g9P`R_h{CTMI16T%fy3nrsO0+%H^1 zwDqRlG=eL4BiwM@p&w9gG)KSu29<}EK(#bDZTvLL-mPNa^IAES_w+qH{1c5LWwEIU zS2$xEL)9tUKh82f#{2&0-A3-CEe0~4uIU-B^Q?JvQR>6kUS|%cdCt9--J66e8ZBaT z=IP~&i9!Npa+JJp;?`R|+D=opE3^I1#^JZgJnB}_TkG$)X5^|S~kBd6+_%@3CHR%iHNKqFy(M9CZkUjKGO)I0Eeq6o8%V|U7 zsiLN=(|ZM3M)Pj?zy&UaUsL8}njTvEAuVT^ z<5Pql=YsV{HO4fLxmUg7j9opgOj!`)N5D!*!x0psV>JztW^pb|N$jMkNNmd2t^Qsf zw&ITwm=ru;G?*FSRa+PJJC@?-XjKNGC(e0@v9YrG`lHAPfz}-hzj}DTAz{a@9G(@# zJoYR;EAtZndD9_hIAG*Gv`J#4B)l>Ba-YFUmy~a!u#mQd5Biw|R;!E*F3lLlMb>W` zUBVUsM@UbWmq$UJ{Oc1_Ih-6iP~EcU!5U8(+wjK)gF8ZKt(8b z613eTD(f_V)k=r?al@G#P>9<(-FY!$e3q8ghfQz+;#Us0dNb4Bd1aFTvtKnH(fgWN zjxx-I&U6TRhX4-5VL3;*wK{&nzhoUmA#o&t0TG|Ws1eOi2*Xdjo9C4MSw5GS$9HfM zbG(aOPeTpafD936jq+wNgmJn}&GgLR`5de|1az*NrG<|16pEZ+05ulaSx5P)Z*-|X zm+Z>o&R^H)%zhC#;f}Re)27>a@>XTx8?C(JRR0NAWOR{0F*H*=`NROhwAc3i41r}a z<=*)SN(pEB_-0sz56GPMzFf%S)RDergo6v`&Q$~KJ$P)k+#H%~K^kf9FZ;wOn2~j` zh_*w^so8LM?KQL&4cZNB12ie^1k*0{WoFnH#*}lnvXflBi#n~=O|4DP`X#~Rjv}|z zWp&TgSzR9}(g3I|#;S}4uPPsaM~`$b|A|%BCl2C&(Fa>uX7wEh)y-jahayoXBAnc~ zA>OI7)$R1hJWt;;LankaJl82b` zS^d1DQDei%%*(p7KWcnQpQuzw+x71r9en5z6Td_0jV3790|v!8dm8uHsv2q#R*!hM zW4O<-DJjZzGV1Nu?{Mj;Bg~&jcH;IlXjS>qg75!TO`Um`yWDkES(saAmbni?#kJ() zCfuJ#84uslbOTlb+}#cIYt!L``IZx6`#>l|Su*rfjXvtvKdaq^xHGJxocLqIaU zdZ5P0w5YTyqYFlm1rHl&aMIH2v|Cxp|L@Z%e8~aW&%7fSE52n^geGwWDW~-Y51!m* z$lb@kJ=2mSigWB*?R|xJesTejy^C=ZdrI9?~+^7aV_uEF_N31xO<)XFK$Y(}$&Y&RVv;8Vo%D=HZF8+@1JD zR0AbTj(2ppDRwDb+0q7aV>ln8)qx)vs2hFj6jCHcn`q~Is#fvKA$hL5wPz>FOd@ki ziouWW)jf*HY`=lmz>sSgRED|4G;*D9UpMttMg6kVp>2iT(mF?CYV;giF+jJ8%H#NQ z^MwbzZ#pbJU~KDk_~=owA8K9f-478N?k_N#Cfhi{Tc#r0_hB~vW#%tGMa5A8o+GSX z|NeFceKBQBI+Jo5TXo>k=s7D63SX>q?(@vrWdR^9ZauqnIdJV0P2+C2pbsBB*E8Gj z*ZsXX1bh?Cyxh*kgMy0@p3=2{h#1*dG#dqp!e4hm*9E1;Ib!~8_Uo^QtQ+2l@}UPj2aHKQDJB;*iq$ko&lmWRo0mOaHStv$ zR%@+fu?5450PXEd5};;74HfhBf?zw1IUoUIdP;*}^|Lc7O)%Kv)9r!6=WW67cc)pb z07h9y6P1@o+K5}3#uO&bnNH!trAyIOpW||?62)X0f3qWuQTIZWSu&i03x5bx1S-3Q z_$Cl#2h6!W;?*kPjNt2q;^RUaZ)WNGN$hUm)69AJS6?y4O354Y=5!6-nUoYxO~LSr zFO3uiVZ+?*3}r@-@zEw`_d!}-v`&=y$@{D;&$?oi;zaDDIEU^jco{8NoW5AgjZUIv zwQb?yQwqPbT2bZ9@X)ExggqB+Ki1fCIBlC*Ve;|g8^(7QR_|L31&^m z1KXWy3&kqzjrmE3kFD$SESq-I%&ARlN1LxngS>&xc%(s?<8PghKzH5T)}-Ff@tx-s z{}CEGB35yp1VN#ZxcP4{hT?6>+F+l4XbYaQS~TmkF>zz%`>S1i%ZP4u8FMDQ2#xY& zl^;AsVg0$;`{G~1Purs+Ka@)(CI&iTr&Ex)3Qesu1rRTs=^r*1-fk>5m3pBQfVgjplN)_0XUhmM+6ME5H1I`lTiU*wl^ak?DH>OGJkb)?*1(o(RC#*bt^)J zQLB#AunDNQ$mEs>k#+TfM;9?GDz5w2Q!oDcrvdgiTzN}oC<5B9toZ&(grBh23-Bn& zUF(O(#Y~{qk^5{4h@DNcQSdTPs1t1$dwjg1GsTfin#9u%+v`JlbyLK$f_J0mr`x%d zf?`zj1B(ZgrryAV=^ zaoNuFFtnGw4@&pZRsNkXT(lPcbFZ&d7F1UneQ-;VwJgoO-@xb%V4SCYHm(2CPv{ni zevbBbaR~z-{Z^ym`x~Ee2f>GuSAX}`ZkoCA@98lo#r{4&U!I%%6>9D~w#Kipcdqf~ z^oNGBe=4YKqU);W_0~l`+S1MY{c}wUcW{6B2tn;Py$ToQvo21%(8D#Iw z_(b4(Y~YjL9dxJplzOA|@61s@qkq)8@tiSeQF9)hK9T3sqcbNmKi|1ak;MvLy7YmM zSJo(aJnJgb9+%&C6!MQgi=JP}N;}8^-yFm(Wp;ERp<*QX^{-SSS%!ccVB*^LnHv=; zv4qRp!i8ls48(DgkGWygod^g^vN*_hXT{kxA1xq$S>-{DkMC`1YdFo`c_7*O9j~G1 zxAlzDT7f+Kf&+Q1I@Cjb!U9ZBt+m``=vkZOoRTto%=+NZXTH53C-BnQw3{J3GqJlb zJo5w16LLdSj}9~W#E9gATn^h^`V$AR#C;9dY{<(Q$*VQ#%*w&CwU0N^jWB3h=TmLlEmYE*h~bXSpD;|s4D;y zpWFQ~9Do0DGS!33|Ma8voRtrb^_2KPDAi+@BdbdAB)_!T!2^y1y?IA$*avLx{)H9| zthG^4|Cj(}Jog%r&2$+CQut^8a71CKD3X6oy&$`REgEKkR|I2 zI4W{78oFsjLsMh#K&!Gqye3AHM3^ybLY`ZAGG+zroFS6 z@?x(i`h>FgYwIK@$NpGJ4F@K5Np|INit86+@oYvpPodfMXIjnLHa@YDL9I0sqL@`j z=MoO-;(j^aIkIBgpMNIY#Uz-j%QS+b(x-p_Ze&XO#}z`lKj(UE;O)Up#?wj~Q!=vRMB?G^6~7@{N9 zMmMdHrEug3ewFc=R>6jy3HmaUk$Un&TtI0w&eV%ev|%1$28Xl~Rp8&njT2Ns`{$&m zXqR<(u|^*R94QBb9wslk1f&dS&K~w{kCRXW$~rjojKV)pE3g0nT?YZ zR^Bg@n-rbpwyr~2o8<{migCoo9sU-}aHR&eg$@!(ZmCzy+Cec3^?qW3z6RB>aNKv=d818-|4Irs@HN-r#rAB(8X4X1A#zm893*(aTC`>IsB z;$w}yhg)l^D@)an+aC6-MB=$K9X_q?2Wz6c(uUQ`qO9>6uHst6bm?~G_ zIleYG?B|Ti)@t9K$~-GRUnwaB)+cmMcMIM9i-RcAS#f7JZ{D@gZZy0tc$lk~{C&F` z@ozL_#&Dx~1}aR%@oChyjNa;=zNCQp3>aFI1SW)yxw;m5A*){j=1EdvNsLg>d8afNK4$RE`Z{UJJ@=_oHgjx zAlC=%2((C(f{jEe5(S+SieH9)HQ~=CyquA;i>`(|3i;&K%hwhI;W&bP-d5Rm5PG9s ztYS;I_=&h{;W4sTVPJR{BNZaoIiDBm$zA4=eqN6hb=E+_Cx<%Ddxaw8Ebb#qzITl@ z?hdgN!wTi8&X2uIddhA#{TTfw6DXZTuE5BJzqPTAh_s6>z>S)w zGAji@RFk`B&YZ+-{OFEJoJou5tVPRO2%Cr$1gUx#qvLrCnULSuZPJ<;n=`2$^T}rQ zYB7I2_;N;NbTm_po8kE2V?3H7%UA6WN~cMWWD3;dWwKRuYZ9!FDWh~hf4c2zlpTA9 zU4_0(38*1AgD+?ngENn&I+XRyAR5|D?5rGMBCwtXnTMv0g2$z}+##UYk1k&nW0ieW37+s$wJ~Q2+_6dZLOeuq zxuy`^1lk_2>lkMjD?YZuy+P(g`=#GGI=p>{4zg6dO8j55tgm~z8(>Y#0dpF6Y!Xmc zQ{6(STAXm5M}9AmaTGK-GEZFNFL}@67~uQnD3vCoSNX)oW*5hqwUx|UuhD{c(-O*i=I;os6W!tTKqee zPEnKv`Bc+@@ecM8r>nCa%vhY}1`a%K+|EkTU7#+RSPRXlb+K87taAdzZ_T;=)xtv! z*25<~M!*-AAJ)}_{uA3t)w z&xxGU33>u?!_kR^+?w=mZfT}iL3uf{^ESNLG#LvrJk+|&gANQ1E-fso(~b97MjCtP zBWM7_>3}i{>PhpTX(4B6j`5GeSo+P=@2_b?d~{ zOFvpa?mI?iwdAK`826KP@i1{}o#!uKj-tQ26xh6Lj~>mku|@R9n^nejKRX1)WyPEE zWwT|tM&SUZHQEy%RLg<$+W=1-IM~w6(30ktLtay>j5K|CpLJBHI(6z$P> zn=MT35Vhf~Kt+`mhFp$%yvBbuy+lF2QT?VG??29GlyV;AOW|}1Nez4s;To(Otrw^L z2rm!RQDf%a1pNTp((j}n=LB26apT5o=$&O@s!bXMCNUO*al-)4+0Rem0AwZ;4_Lsm zt$k#^8e50o|2vSvzi&%YmZ!b01_Nk*WAU>$x0n|mxCFZ4J2aJ9=G5!Wg`rT!rV zwjN<-JWD-`c*;JbF%UXxmcfQ2Dv=Et@bOy~A53!b<&iBpjY8UYd07JNCN?75u#DW2>dVsVv%0(#%06>m&Z)(3+|QD&UW~o49E3xdnEVI@7NGm_~lv-v-6i?{XrHcqqa2;@TTIS_-2_4{o)h2sX$As}lK_j5{ z$X8+v3G`Ms)?bzIZ)4z@bBjV#V5vPxp#?ZyLFUX9$UCYOmR&B2=}PXWl||JwtE`7R(I& zx<4G6y1F#Ab|3Zq{(=^Ve!hRxW3{<|#u%o;JX+7Tw%9~U%a%N{bUJEt%h8JE;00p& z#7H#im~2SE3lgS_f9NKEmyWo3@@lh#CM-RNWFR-+4tfrjFCtD96 z0|55|sOSGNDZNNaGP9VptXcEsB56eGoC_B&C$72J-QpVg6J=A4R@qv?n4;1J%n|`q zN*Mz#v1eoVBC$?Cx`THz{dP49Az@?Zoka8jTo@p$c$;qWH@KOfuls)+eX=y*N8@hO zUdd)%8ZbJVb_kdpViTlO@jii!^6lmDigO~nQOPr=;A4Wh zzwTB40V_a#9{E(P!XC%k=15A4IZD`c-GgR|A+W*42OQ=^(`*K~k5+!Ll1&Gdjg0dv zi2IUx3ZO}wj~w}XWve4$o>=)a%$sF697#_bdL0E4Ym@h4K|pp^YIVfWFZSa z#almp{Yi$!0MXah8{78eOfl`QDZh#@WeP$>*$71LMCuK@$a4e4(6dlRICScmg0DgF z)~)A%mPKBB*CBT2?Ym*Pw?K=AQ!?b`q^P}B zJ7gHIQhSUT#Cef|tyUSanWXy8ZMueR001BnKKIC*Sb4~9a5S5soMt~+dx~y`%f5}9 z%q|O&NvC(7IeN61YOY}@rJOsraZw%-te~J^FRVPe`9(gC0jk$zVHhN5nTGa-$1_qC zGq`z)qh69rs)4ELyZkhtcJg2PxUJ!V$>gB28A|{6w(F$C$Zh}n3BQ673Por^`$14T zL~+lB{F!2%^Ma5iA(P*}o_2C%KEMH=UG&6ti~KDbP=$)cG%4YB!sPxVzoVvGOOmG_ zS6VeYtpk~YNx8bOA_q~28%ovw z*iF%e(XhMl9YN@j5mgqKZiHzW9C8J!7`6nrpfp`eXbvia`PqR-0I-$0xZn4yw{DGw zfD&pMoqiHe7qN&V92XC6rLLnwth0B&>phb}P($Hp3zZvE?8sGcphcr8{#amf9FF2Z zZuxnn%>cQ{+(>*mu!$73k8x0Sg!1%&b*3Dj-&56&9agZ4nRE&3PH$QnRHe}%RE9>` zpic0ue`Vv|zY)hVK7|k)#z;}@x)5^flmOlmt1o*VOs!pG?Ub*Bs~6qpBqp=kORyyO zRLHnMFzX=8Gjg<@$L^>alo-6kLGG>~ZG5n51XS&;qPsGG$4*380`9B8xgc@Q$xR}4 zsz1DT(bQM@u|ImiaFZRP)O3tMT4X~h3KZO#N*F^X%G{jJ=&3FX;e)Icq*Yd1OUDfx zKyhlJOjq<`Jj+WYYiD)Fgy;ew@$sd?BEHnsOqp2KAHk=Q{wQ~imX|up$8|5hXk9j& zXxxaTZI1H?D8+y?>FE9-ZCqwDT-JKC@+e%q0$J_Jv2uEyacfPr8iHNoUh?-~UG1D% z)DAMoWpb|>X4y$KWbk0v3|caG)pO1fc`=|0y`4@8wjIC23T2M*@8@@jzhRuK@G-!Q zkODJx>7VyBH0ouKH5;k8C?@EyJt5J7tH|zUmLi(O><{lqt3@7MXBUfh@=SUzK2Wu} zSn*Bsar9SRgA`GKlL&x$JtgGS-(E&66Q#bOdcjH4VTbY255e`3Legfz{llHk{3!Pn zT=L)Go0Ig~C}&S#P|zjbM}I_bi(EgHmVBZt9?dkebjRk4p@06_fY%7Dcl!#ry(A#X z1CmiF485%_%)D%obyB!GCQSOB>@_l#NL9B{qsu6V%`85xq)YN;@=x53OMcCWfs8E( zZ^l)1{PQo3c|A}NpqzP_dyDHKEN$1*c2b*gxS}(P28-#CzQIQJ+eE6P2q~*#R~iydy`# zn0!X1l(A|auO@7_jr`her*b`a9ypan=^+3#@!^lJc@#*~5wOCi9je&kU-}x0H*vmV z`T5@DUg?vq1q?-yN-yh!us zdxcgoD<}v)!WLv!(R<}8?umBe#u{Ydwj(U*{>WD(b=Wxvl85omB)F!v71;U95n^g3 zoQ-DOAk5Nc88i}Zn6$jIr>JK;j)C5XP(|tCQLW!6wo|HT|>aiBQLNjI^+9;ATNUtgaRx5Ks!=^U)oEGfTFk5)9IHg1}on2-Pv z32NR5ddargVk1LdWJyD_Y|vpb-9x9bsbY8)g}zL8S8-uC{N@-~3PVJ^ulDXOSog-` z-XT52E!9NB(Xy{^9p~anOx%Bzm-I%$CYMEP*WBBcC@S{Mr}+akFL5tI&CE_N{=Xwr zu7$Hf2u2u$nZ_!V3I9Q}oWk~utb(jI9Ex?(rq&i|!CQ(+8pl}EH~2F{&pr#0Oh%}p z)9syFYG>Fb(TPaP@-9E>w;Di!qfAZD*B|p?=uCHa>@3=0*H!~{R?eTH{wi-)D*Ox3 z&Emv~FcShKe%~XbU$V=P%F|}*6xN62wT5(TtFoCF9Ai58x9ccKn>!oGD z;3uFX&#NO7OaL5EGY9vqyq6#~gBCrnOMn!cYVnK(sa3uGN_8(gq0wH}Vr&?{WO0DM zs`K^AtZj2*$Tc-WS#8LWQ@=a{uyGPKLo%}*b)E-t!XV)&`1Jg)- zCOoX)R1ZEJWfZ{l1R;$HhWNfb(%fC6zryDX{`1eN<#?bsk#CZDbp8QG1`PGilh0-8 z6-b<;{dE1vaFGS=F!XGZH1&kOYG-)3sX^FN*3$TrHPb&apm|0dOy{H5O5tsJva$D> z+eHaW)gdL)c)gXE^9hF7VyPtNDRcv8foI~E?15%4MX^wAA|iCzA#xiSl=eNz(P$8C zdG_*c1|Vb^gD&qr>%uNE`LPXaXTp$NmdnX5A;yRW&z~!_Vgvk@$7qP=Pg$_&Hs6wYplwOQE5*#uK$foRAu*g`yOQM z9I^oTC?ZW3BKA?txTsM^(v3`;H%|+4N2<{y5svfnJ_RU2r%;<}PBu?r7V(rg^%ssr z>0i>qa6e&byFW)^v5|?kZL9yPi8(nOr;BL%4j~bc$-Jm+PA5^+i|(50GiJ+`s=ScG z%ULdzQ#>hvmqKsV&$xCi>&s%mAIn`O44uSYf-)eJ7J}klwz;AqRd%Qb6%QAJw{M?} zq8AKH!t-rZwA~X*#@{}_)q|()ht@-nT{XOF(ly*|*KE#o1g=cG&(qn#yM^gw#s~NM z(MCV=r1(%!5B3#d_Ch~Lexae!oocKa`2~(bCk6#m^82d6SO4OAMmd+Z@-%5h|G3p` zII|zXnTwmFCo=Sc66Hr_&W)FlNO8;soBcD#%q&It98yr=s&V>lO5&81^CTdNh$VVe z6|8N<`514jtrU=y2(p<|41}b6VJ@FjKI;^__*jOcFm5NSD;a03PfcBQqD~R?jKb#4 znz@lrC9m2}n$%T=UqAfw`u%op+JCgF7>HYMRhB3IHQ2=ug@NmLZl(#0V=wD4mFVPx|*e&PlTS~|Fh~) zni%Dj_?|z1K5OtxU>#GOg~fLejGt1eF1>O(Hx4Tl=knb=B9DicJ}*f(){tj={(N=J^C?~fHIwUD3bpP!@ksH)^iCDQQ_$)uc6qO~wRb2j`eTlMp&+gE|ia+6fP_Y~@pf91EtwKvMC qdgSt_2LAGce||;Q`~UN;<*rdr7ZyKn+006Vud(LVW=W=QzW)p8?{oeD literal 0 HcmV?d00001 From 838e37ca98ed4393d9d37208eb1b8cb55a4d0754 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 1 Apr 2020 08:45:27 -0700 Subject: [PATCH 252/459] Python: ObjectAPI to ValueAPI: ReturnValueIgnore: Moves getAnInferredType to CallableObjectInternal --- python/ql/src/Functions/ReturnValueIgnored.ql | 3 +- .../src/semmle/python/objects/Callables.qll | 7 ++++ .../src/semmle/python/objects/ObjectAPI.qll | 39 ------------------- 3 files changed, 9 insertions(+), 40 deletions(-) diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index 02cc9eff368..346e9a19d27 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -15,6 +15,7 @@ */ import python +import semmle.python.objects.Callables predicate meaningful_return_value(Expr val) { val instanceof Name @@ -44,7 +45,7 @@ predicate returns_meaningful_value(FunctionValue f) { or /* Is f a builtin function that returns something other than None? * Ignore __import__ as it is often called purely for side effects */ - f.isBuiltin() and f.getAnInferredReturnType() != ClassValue::nonetype() and not f.getName() = "__import__" + f.isBuiltin() and f.(CallableObjectInternal).getAnInferredReturnType() != ClassValue::nonetype() and not f.getName() = "__import__" ) } diff --git a/python/ql/src/semmle/python/objects/Callables.qll b/python/ql/src/semmle/python/objects/Callables.qll index b915e4bd5c2..010b2c89197 100644 --- a/python/ql/src/semmle/python/objects/Callables.qll +++ b/python/ql/src/semmle/python/objects/Callables.qll @@ -49,6 +49,13 @@ abstract class CallableObjectInternal extends ObjectInternal { /* Callables aren't iterable */ override ObjectInternal getIterNext() { none() } + + /** Gets a class that this function may return */ + ClassValue getAnInferredReturnType() { + result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType()) + or + result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType()) + } } /** Class representing Python functions */ diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 403b0bb0c84..61e3f17c5d7 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -581,13 +581,6 @@ abstract class FunctionValue extends CallableValue { exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | not origin instanceof Lambda) ) } - - /** Gets a class that this function may return */ - ClassValue getAnInferredReturnType() { - result = this.(BuiltinFunctionValue).getAReturnType() - or - result = this.(BuiltinMethodValue).getAReturnType() - } } /** Class representing Python functions */ @@ -627,29 +620,6 @@ class BuiltinFunctionValue extends FunctionValue { override int minParameters() { none() } override int maxParameters() { none() } - - ClassValue getAReturnType() { - /* Enumerate the types of a few builtin functions, that the CPython analysis misses. - */ - this = TBuiltinFunctionObject(Builtin::builtin("hex")) and result = ClassValue::str() - or - this = TBuiltinFunctionObject(Builtin::builtin("oct")) and result = ClassValue::str() - or - this = TBuiltinFunctionObject(Builtin::builtin("intern")) and result = ClassValue::str() - or - /* Fix a few minor inaccuracies in the CPython analysis */ - exists(Builtin mthd, Builtin cls | this = TBuiltinFunctionObject(mthd) and result = TBuiltinClassObject(cls) - | ext_rettype(mthd, cls)) and - not ( - this = TBuiltinFunctionObject(Builtin::builtin("__import__")) and result = ClassValue::nonetype() - or - this = TBuiltinFunctionObject(Builtin::builtin("compile")) and result = ClassValue::nonetype() - or - this = TBuiltinFunctionObject(Builtin::builtin("sum")) - or - this = TBuiltinFunctionObject(Builtin::builtin("filter")) - ) - } } /** Class representing builtin methods, such as `list.append` or `set.add` */ @@ -667,15 +637,6 @@ class BuiltinMethodValue extends FunctionValue { override int minParameters() { none() } override int maxParameters() { none() } - - ClassValue getAReturnType() { - exists(Builtin mthd, Builtin cls | - this = TBuiltinMethodObject(mthd) and - result = TBuiltinClassObject(cls) - | - ext_rettype(mthd, cls) - ) - } } /** From 36c351dc68e280d4baaa02a6d25a8469944afa01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Wed, 1 Apr 2020 17:59:45 +0200 Subject: [PATCH 253/459] Add input from documentation review --- .../experimental/Security/CWE/CWE-036/OpenStream.qhelp | 8 ++++---- .../src/experimental/Security/CWE/CWE-036/OpenStream.ql | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp index e9cc9a0ebb2..d0542240daa 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp @@ -5,15 +5,15 @@

    Calling openStream on URLs created from remote source can lead to local file disclosure.

    -

    If openStream is called on a java.net.URL, that was created from a remote source +

    If openStream is called on a java.net.URL, that was created from a remote source, an attacker can try to pass absolute URLs starting with file:// or jar:// to access local resources in addition to remote ones.

    -

    When you construct a URL using java.net.URL from a remote source, make sure -to not call openStream on it. Instead fetch the URL with a HTTP Client to access its content. -Also validate that the URL uses the correct protocol and host combination.

    +

    When you construct a URL using java.net.URL from a remote source, +don't call openStream on it. Instead, use an HTTP Client to fetch the URL and access its content. +You should also validate the URL to check that it uses the correct protocol and host combination.

    diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql index 702e11b8740..ab315277f2b 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql @@ -1,8 +1,7 @@ /** - * @name Calling openStream on URLs created from remote source can lead to file disclosure - * @description If openStream is called on a java.net.URL, that was created from a remote source - * an attacker can try to pass absolute URLs starting with file:// or jar:// to access - * local resources in addition to remote ones. + * @name openStream called on URLs created from remote source + * @description Calling openStream on URLs created from remote source + * can lead to local file disclosure. * @kind path-problem */ From 7a989198792d75fa9a07979acebfa97a043b955f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 1 Apr 2020 17:06:02 +0100 Subject: [PATCH 254/459] C++: Add a non-standard swap to taint tests. --- .../dataflow/taint-tests/localTaint.expected | 17 ++++++++++++ .../dataflow/taint-tests/taint.cpp | 26 ++++++++++++++++++- .../dataflow/taint-tests/taint.expected | 3 +++ .../dataflow/taint-tests/test_diff.expected | 1 + .../dataflow/taint-tests/test_ir.expected | 2 ++ 5 files changed, 48 insertions(+), 1 deletion(-) 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 648159b4944..4c0fe0f8161 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -512,3 +512,20 @@ | taint.cpp:444:7:444:7 | d [post update] | taint.cpp:447:7:447:7 | d | | | taint.cpp:445:2:445:2 | d [post update] | taint.cpp:446:7:446:7 | d | | | taint.cpp:445:2:445:2 | d [post update] | taint.cpp:447:7:447:7 | d | | +| taint.cpp:452:16:452:16 | a | taint.cpp:454:10:454:10 | a | | +| taint.cpp:452:24:452:24 | b | taint.cpp:455:6:455:6 | b | | +| taint.cpp:454:10:454:10 | a | taint.cpp:456:6:456:6 | c | | +| taint.cpp:455:6:455:6 | b | taint.cpp:452:16:452:16 | a | | +| taint.cpp:455:6:455:6 | b | taint.cpp:455:2:455:6 | ... = ... | | +| taint.cpp:456:6:456:6 | c | taint.cpp:452:24:452:24 | b | | +| taint.cpp:456:6:456:6 | c | taint.cpp:456:2:456:6 | ... = ... | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:462:2:462:13 | ... = ... | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:465:7:465:7 | x | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:468:7:468:7 | x | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:470:7:470:7 | x | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:463:2:463:6 | ... = ... | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:466:7:466:7 | y | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:468:10:468:10 | y | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:471:7:471:7 | y | | +| taint.cpp:468:7:468:7 | ref arg x | taint.cpp:470:7:470:7 | x | | +| taint.cpp:468:10:468:10 | ref arg y | taint.cpp:471:7:471:7 | y | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 3fff2fd7229..5d8327017fa 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -195,7 +195,7 @@ void test_memcpy(int *source) { sink(x); } -// --- swap --- +// --- std::swap --- namespace std { template constexpr void swap(T& a, T& b); @@ -446,3 +446,27 @@ void test_qualifiers() sink(d); // tainted sink(d.getString()); // tainted } + +// --- non-standard swap --- + +void swop(int &a, int &b) +{ + int c = a; + a = b; + b = c; +} + +void test_swop() { + int x, y; + + x = source(); + y = 0; + + sink(x); // tainted + sink(y); // clean + + swop(x, y); + + sink(x); // clean [FALSE POSITIVE] + sink(y); // tainted +} 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 46146094e53..7061beff0ee 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -58,3 +58,6 @@ | taint.cpp:439:10:439:18 | call to getMember | taint.cpp:437:15:437:20 | call to source | | taint.cpp:446:7:446:7 | d | taint.cpp:445:14:445:28 | call to source | | taint.cpp:447:9:447:17 | call to getString | taint.cpp:445:14:445:28 | call to source | +| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source | +| 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 | 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 7680193da16..329a0bb6ecc 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 @@ -42,3 +42,4 @@ | taint.cpp:439:10:439:18 | taint.cpp:437:15:437:20 | AST only | | 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 | 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 b38de345220..b0107791e61 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 @@ -20,3 +20,5 @@ | taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source | | taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source | | taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source | +| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source | +| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source | From b07380d2ebfc12e5e422b96c9e75043a2aa4ef6d Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 1 Apr 2020 20:19:00 +0200 Subject: [PATCH 255/459] C++: Update ppReprType for C++ IR dataflow I forgot to do this in b1be123e31. Without this change, we suffix ` : void` on very step of an IR path explanation. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 6db341c2cbc..9aa19d57785 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -154,7 +154,7 @@ Type getErasedRepr(Type t) { } /** Gets a string representation of a type returned by `getErasedRepr`. */ -string ppReprType(Type t) { result = t.toString() } +string ppReprType(Type t) { none() } // stub implementation /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from From 207c76b8558b324dec2fa279ce9830c574128cf7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 1 Apr 2020 20:36:25 +0200 Subject: [PATCH 256/459] C++: Path explanations in DefaultTaintTracking The first three queries are migrated to use path explanations. --- .../src/Security/CWE/CWE-022/TaintedPath.ql | 16 +- .../CWE/CWE-134/UncontrolledFormatString.ql | 16 +- .../CWE/CWE-190/TaintedAllocationSize.ql | 34 ++- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 134 +++++++++ .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 1 + .../CWE-022/semmle/tests/TaintedPath.expected | 12 +- .../CWE-134/semmle/argv/argvLocal.expected | 270 ++++++++++++++++-- .../CWE-134/semmle/funcs/funcsLocal.expected | 63 +++- .../UncontrolledFormatString.expected | 10 + .../CWE/CWE-134/semmle/ifs/ifs.expected | 130 ++++++++- .../TaintedAllocationSize.expected | 93 +++++- 11 files changed, 704 insertions(+), 75 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 42a29b96268..496b957cca3 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -2,7 +2,7 @@ * @name Uncontrolled data used in path expression * @description Accessing paths influenced by users can allow an * attacker to access unexpected resources. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/path-injection @@ -17,6 +17,7 @@ import cpp import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath /** * A function for opening a file. @@ -51,12 +52,19 @@ class FileFunction extends FunctionWithWrappers { override predicate interestingArg(int arg) { arg = 0 } } +class TaintedPathConfiguration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(FileFunction fileFunction | fileFunction.outermostWrapperFunctionCall(tainted, _)) + } +} + from - FileFunction fileFunction, Expr taintedArg, Expr taintSource, string taintCause, string callChain + FileFunction fileFunction, Expr taintedArg, Expr taintSource, PathNode sourceNode, + PathNode sinkNode, string taintCause, string callChain where fileFunction.outermostWrapperFunctionCall(taintedArg, callChain) and - tainted(taintSource, taintedArg) and + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and isUserInput(taintSource, taintCause) -select taintedArg, +select taintedArg, sourceNode, sinkNode, "This argument to a file access function is derived from $@ and then passed to " + callChain, taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql index 02a0f42fa6b..03d8e4bfb45 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql @@ -3,7 +3,7 @@ * @description Using externally-controlled format strings in * printf-style functions can lead to buffer overflows * or data representation problems. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/tainted-format-string @@ -16,12 +16,20 @@ import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -from PrintfLikeFunction printf, Expr arg, string printfFunction, Expr userValue, string cause +class TaintedPathConfiguration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _)) + } +} + +from PrintfLikeFunction printf, Expr arg, PathNode sourceNode, + PathNode sinkNode, string printfFunction, Expr userValue, string cause where printf.outermostWrapperFunctionCall(arg, printfFunction) and - tainted(userValue, arg) and + taintedWithPath(userValue, arg, sourceNode, sinkNode) and isUserInput(userValue, cause) -select arg, +select arg, sourceNode, sinkNode, "The value of this argument may come from $@ and is being used as a formatting argument to " + printfFunction, userValue, cause diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 85248a26d19..2ed95e6cb55 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -2,7 +2,7 @@ * @name Overflow in uncontrolled allocation size * @description Allocating memory with a size controlled by an external * user can result in integer overflow. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cpp/uncontrolled-allocation-size @@ -13,21 +13,33 @@ import cpp import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -predicate taintedAllocSize(Expr e, Expr source, string taintCause) { +predicate taintedChild(Expr e, Expr tainted) { ( - isAllocationExpr(e) or + isAllocationExpr(e) + or any(MulExpr me | me.getAChild() instanceof SizeofOperator) = e ) and + tainted = e.getAChild() and + tainted.getUnspecifiedType() instanceof IntegralType +} + +class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { taintedChild(_, tainted) } +} + +predicate taintedAllocSize( + Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause +) { + isUserInput(source, taintCause) and exists(Expr tainted | - tainted = e.getAChild() and - tainted.getUnspecifiedType() instanceof IntegralType and - isUserInput(source, taintCause) and - tainted(source, tainted) + taintedChild(e, tainted) and + taintedWithPath(source, tainted, sourceNode, sinkNode) ) } -from Expr e, Expr source, string taintCause -where taintedAllocSize(e, source, taintCause) -select e, "This allocation size is derived from $@ and might overflow", source, - "user input (" + taintCause + ")" +from Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause +where taintedAllocSize(e, source, sourceNode, sinkNode, taintCause) +select e, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow", + source, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index d932ad30b87..c0f763a78bc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -2,6 +2,7 @@ import cpp import semmle.code.cpp.security.Security private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.dataflow.DataFlow2 +private import semmle.code.cpp.ir.dataflow.DataFlow3 private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch private import semmle.code.cpp.models.interfaces.Taint @@ -171,6 +172,7 @@ private predicate nodeIsBarrierIn(DataFlow::Node node) { node = getNodeForSource(any(Expr e)) } +cached private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Expressions computed from tainted data are also tainted exists(CallInstruction call, int argIndex | call = i2 | @@ -381,3 +383,135 @@ Function resolveCall(Call call) { result = Dispatch::viableCallable(callInstruction) ) } + +/** + * Provides definitions for augmenting source/sink pairs with data-flow paths + * between them. From a `@kind path-problem` query, import this module in the + * global scope, extend `TaintTrackingConfiguration`, and use `taintedWithPath` + * in place of `tainted`. + * + * Importing this module will also import the query predicates that contain the + * taint paths. + */ +module TaintedWithPath { + /** + * A taint-tracking configuration that matches sources and sinks in the same + * way as the `tainted` predicate. + */ + class TaintTrackingConfiguration extends int { + TaintTrackingConfiguration() { this = 1 } + + /** Override this to specify which elements are sinks in this configuration. */ + abstract predicate isSink(Element e); + } + + private class AdjustedConfiguration extends DataFlow3::Configuration { + AdjustedConfiguration() { this = "AdjustedConfiguration" } + + override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) } + + override predicate isSink(DataFlow::Node sink) { + exists(TaintTrackingConfiguration cfg | cfg.isSink(adjustedSink(sink))) + } + + override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + instructionTaintStep(n1.asInstruction(), n2.asInstruction()) + } + + override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) } + + override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) } + } + + /* + * A sink `Element` may map to multiple `DataFlowX::PathNode`s via (the + * inverse of) `adjustedSink`. For example, an `Expr` maps to all its + * conversions, and a `Variable` maps to all loads and stores from it. Because + * the path node is part of the tuple that constitutes the alert, this leads + * to duplicate alerts. + * + * To avoid showing duplicates, we edit the graph to replace the final node + * coming from the data-flow library with a node that matches exactly the + * `Element` sink that's requested. + * + * The same should ideally be done with the source, but we haven't seen a + * need for it yet. + */ + + private newtype TPathNode = + TWrapPathNode(DataFlow3::PathNode n) or + TFinalPathNode(Element e) { exists(TaintTrackingConfiguration cfg | cfg.isSink(e)) } + + /** An opaque type used for the nodes of a data-flow path. */ + class PathNode extends TPathNode { + /** Gets a textual representation of this element. */ + string toString() { none() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + none() + } + } + + private class WrapPathNode extends PathNode, TPathNode { + DataFlow3::PathNode inner() { this = TWrapPathNode(result) } + + override string toString() { result = this.inner().toString() } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.inner().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + private class FinalPathNode extends PathNode, TFinalPathNode { + Element inner() { this = TFinalPathNode(result) } + + override string toString() { result = this.inner().toString() } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this + .inner() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { + DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), b.(WrapPathNode).inner()) + or + // To avoid showing trivial-looking steps, we replace the last node instead + // of adding an edge out of it. + exists(WrapPathNode replaced | + DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), replaced.inner()) and + b.(FinalPathNode).inner() = adjustedSink(replaced.inner().getNode()) + ) + } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + predicate taintedWithPath(Expr source, Element tainted, PathNode sourceNode, PathNode sinkNode) { + exists(AdjustedConfiguration cfg, DataFlow3::PathNode sinkInner, DataFlow::Node sink | + sourceNode.(WrapPathNode).inner().getNode() = getNodeForSource(source) and + sinkInner.getNode() = sink and + cfg.hasFlowPath(sourceNode.(WrapPathNode).inner(), sinkInner) and + tainted = adjustedSink(sinkInner.getNode()) and + tainted = sinkNode.(FinalPathNode).inner() + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index e19912a63ee..0ecb4ac596a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -323,6 +323,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) } +cached private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) { iTo.(CopyInstruction).getSourceValue() = iFrom or diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected index 7a58fb1b608..e84389872fd 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected @@ -1 +1,11 @@ -| test.c:17:11:17:18 | fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename) | test.c:9:23:9:26 | argv | user input (argv) | +edges +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | (const char *)... | +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | +nodes +| test.c:9:23:9:26 | argv | semmle.label | argv | +| test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | +| test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | +| test.c:17:11:17:18 | fileName | semmle.label | fileName | +| test.c:27:11:27:18 | fileName | semmle.label | fileName | +#select +| test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename) | test.c:9:23:9:26 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index 7f342b0aabe..b33bdb63e94 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -1,28 +1,242 @@ -| argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:95:9:95:12 | argv | argv | -| argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:96:15:96:18 | argv | argv | -| argvLocal.c:101:9:101:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:102:15:102:16 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:106:9:106:13 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:107:15:107:19 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:110:9:110:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:111:15:111:17 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:116:9:116:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:117:15:117:16 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:121:9:121:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:122:15:122:16 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:127:9:127:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:128:15:128:16 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:131:9:131:14 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:132:15:132:20 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:135:9:135:12 | ... ++ | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:136:15:136:18 | -- ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:144:9:144:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:145:15:145:16 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:150:9:150:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:149:11:149:14 | argv | argv | -| argvLocal.c:151:15:151:16 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:149:11:149:14 | argv | argv | -| argvLocal.c:157:9:157:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:156:23:156:26 | argv | argv | -| argvLocal.c:158:15:158:16 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:156:23:156:26 | argv | argv | -| argvLocal.c:164:9:164:11 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:163:22:163:25 | argv | argv | -| argvLocal.c:165:15:165:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:163:22:163:25 | argv | argv | -| argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:168:18:168:21 | argv | argv | -| argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:168:18:168:21 | argv | argv | +edges +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | (const char *)... | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | (const char *)... | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | (const char *)... | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | (const char *)... | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (const char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +nodes +| argvLocal.c:15:9:15:17 | Correct | semmle.label | Correct | +| argvLocal.c:16:15:16:23 | Correct | semmle.label | Correct | +| argvLocal.c:20:9:20:10 | c1 | semmle.label | c1 | +| argvLocal.c:21:15:21:16 | c1 | semmle.label | c1 | +| argvLocal.c:25:9:25:10 | c2 | semmle.label | c2 | +| argvLocal.c:26:15:26:16 | c2 | semmle.label | c2 | +| argvLocal.c:30:9:30:11 | * ... | semmle.label | * ... | +| argvLocal.c:31:15:31:17 | * ... | semmle.label | * ... | +| argvLocal.c:36:9:36:10 | c4 | semmle.label | c4 | +| argvLocal.c:37:15:37:16 | c4 | semmle.label | c4 | +| argvLocal.c:41:9:41:10 | c5 | semmle.label | c5 | +| argvLocal.c:42:15:42:16 | c5 | semmle.label | c5 | +| argvLocal.c:47:9:47:10 | c6 | semmle.label | c6 | +| argvLocal.c:48:15:48:16 | c6 | semmle.label | c6 | +| argvLocal.c:51:9:51:21 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:52:15:52:27 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:55:9:55:12 | ... ++ | semmle.label | ... ++ | +| argvLocal.c:56:15:56:18 | -- ... | semmle.label | -- ... | +| argvLocal.c:59:9:59:20 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:60:15:60:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:63:9:63:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:64:15:64:32 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:68:9:68:10 | c7 | semmle.label | c7 | +| argvLocal.c:69:15:69:16 | c7 | semmle.label | c7 | +| argvLocal.c:74:9:74:10 | c8 | semmle.label | c8 | +| argvLocal.c:75:15:75:16 | c8 | semmle.label | c8 | +| argvLocal.c:80:9:80:10 | c9 | semmle.label | c9 | +| argvLocal.c:81:15:81:16 | c9 | semmle.label | c9 | +| argvLocal.c:86:9:86:11 | c91 | semmle.label | c91 | +| argvLocal.c:87:15:87:17 | c91 | semmle.label | c91 | +| argvLocal.c:91:18:91:20 | c10 | semmle.label | c10 | +| argvLocal.c:92:24:92:26 | c10 | semmle.label | c10 | +| argvLocal.c:95:9:95:12 | argv | semmle.label | argv | +| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | +| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | +| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | +| argvLocal.c:96:15:96:18 | argv | semmle.label | argv | +| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | +| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | +| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | +| argvLocal.c:100:7:100:10 | argv | semmle.label | argv | +| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | +| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | +| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | +| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | +| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | +| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | +| argvLocal.c:105:14:105:17 | argv | semmle.label | argv | +| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | +| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | +| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | +| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | +| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | +| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | +| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | +| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | +| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | +| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | +| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | +| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | +| argvLocal.c:115:13:115:16 | argv | semmle.label | argv | +| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | +| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 | +| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | +| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | +| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | +| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | +| argvLocal.c:126:10:126:13 | argv | semmle.label | argv | +| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | +| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 | +| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | +| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | +| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | +| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | +| argvLocal.c:139:9:139:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:140:15:140:32 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | +| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | +| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | +| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | +| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | +| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | +| argvLocal.c:149:11:149:14 | argv | semmle.label | argv | +| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | +| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | +| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | +| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | +| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | +| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | +| argvLocal.c:156:23:156:26 | argv | semmle.label | argv | +| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:157:9:157:10 | i9 | semmle.label | i9 | +| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | +| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | +| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | +| argvLocal.c:163:22:163:25 | argv | semmle.label | argv | +| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:164:9:164:11 | i91 | semmle.label | i91 | +| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | +| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | +| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | +| argvLocal.c:168:18:168:21 | argv | semmle.label | argv | +| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | +| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | +| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | +| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | +| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | +| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | +#select +| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:95:9:95:12 | argv | argv | +| argvLocal.c:96:15:96:21 | access to array | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:96:15:96:18 | argv | argv | +| argvLocal.c:101:9:101:10 | i1 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:102:15:102:16 | i1 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:106:9:106:13 | access to array | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:107:15:107:19 | access to array | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:110:9:110:11 | * ... | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:111:15:111:17 | * ... | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:116:9:116:10 | i3 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:117:15:117:16 | i3 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:121:9:121:10 | i4 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:122:15:122:16 | i4 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:127:9:127:10 | i5 | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:128:15:128:16 | i5 | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:131:9:131:14 | ... + ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:132:15:132:20 | ... + ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:135:9:135:12 | ... ++ | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:136:15:136:18 | -- ... | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:144:9:144:10 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:145:15:145:16 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:150:9:150:10 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:149:11:149:14 | argv | argv | +| argvLocal.c:151:15:151:16 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:149:11:149:14 | argv | argv | +| argvLocal.c:157:9:157:10 | i9 | argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:156:23:156:26 | argv | argv | +| argvLocal.c:158:15:158:16 | i9 | argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:156:23:156:26 | argv | argv | +| argvLocal.c:164:9:164:11 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:163:22:163:25 | argv | argv | +| argvLocal.c:165:15:165:17 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:163:22:163:25 | argv | argv | +| argvLocal.c:169:18:169:20 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:168:18:168:21 | argv | argv | +| argvLocal.c:170:24:170:26 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:168:18:168:21 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 2417990beb2..889552641ef 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -1,7 +1,56 @@ -| funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | -| funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:26:8:26:9 | i3 | fgets | -| funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets | -| funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:19:31:21 | i41 | fgets | -| funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | -| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets | -| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets | +edges +| funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | (const char *)... | +| funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | (const char *)... | +| funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | i6 | +nodes +| funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | semmle.label | BufferMayWriteSideEffect | +| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 | +| funcsLocal.c:22:9:22:12 | %s | semmle.label | %s | +| funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 | +| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | +| funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | +| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | +| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | +| funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 | +| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | +| funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | +| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | +| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | +| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | +| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | +| funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 | +#select +| funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | +| funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:26:8:26:9 | i3 | fgets | +| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets | +| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:19:31:21 | i41 | fgets | +| funcsLocal.c:37:9:37:10 | i5 | funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | +| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets | +| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected index e69de29bb2d..09f550d1bd4 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected @@ -0,0 +1,10 @@ +edges +nodes +| globalVars.c:27:9:27:12 | copy | semmle.label | copy | +| globalVars.c:30:15:30:18 | copy | semmle.label | copy | +| globalVars.c:33:9:33:12 | %s | semmle.label | %s | +| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | +| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | +| globalVars.c:44:9:44:12 | %s | semmle.label | %s | +| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | +#select diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected index d474364a0cc..4a96784b3a4 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected @@ -1,11 +1,119 @@ -| ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:61:8:61:11 | argv | argv | -| ifs.c:69:9:69:10 | c8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:68:8:68:11 | argv | argv | -| ifs.c:75:9:75:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:74:8:74:11 | argv | argv | -| ifs.c:81:9:81:10 | i2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:80:8:80:11 | argv | argv | -| ifs.c:87:9:87:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:86:8:86:11 | argv | argv | -| ifs.c:93:9:93:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:92:8:92:11 | argv | argv | -| ifs.c:99:9:99:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:98:8:98:11 | argv | argv | -| ifs.c:106:9:106:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:105:8:105:11 | argv | argv | -| ifs.c:112:9:112:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:111:8:111:11 | argv | argv | -| ifs.c:118:9:118:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:117:8:117:11 | argv | argv | -| ifs.c:124:9:124:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:123:8:123:11 | argv | argv | +edges +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | (const char *)... | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | (const char *)... | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | (const char *)... | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | (const char *)... | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | (const char *)... | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | (const char *)... | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | (const char *)... | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | (const char *)... | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | (const char *)... | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | (const char *)... | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | (const char *)... | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +nodes +| ifs.c:26:9:26:10 | c1 | semmle.label | c1 | +| ifs.c:32:9:32:10 | c2 | semmle.label | c2 | +| ifs.c:38:9:38:10 | c3 | semmle.label | c3 | +| ifs.c:44:9:44:10 | c4 | semmle.label | c4 | +| ifs.c:50:9:50:10 | c5 | semmle.label | c5 | +| ifs.c:56:9:56:10 | c6 | semmle.label | c6 | +| ifs.c:61:8:61:11 | argv | semmle.label | argv | +| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | +| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | +| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | +| ifs.c:68:8:68:11 | argv | semmle.label | argv | +| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | +| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | +| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | +| ifs.c:74:8:74:11 | argv | semmle.label | argv | +| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | +| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | +| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | +| ifs.c:80:8:80:11 | argv | semmle.label | argv | +| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | +| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | +| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | +| ifs.c:86:8:86:11 | argv | semmle.label | argv | +| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | +| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | +| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | +| ifs.c:92:8:92:11 | argv | semmle.label | argv | +| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | +| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | +| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | +| ifs.c:98:8:98:11 | argv | semmle.label | argv | +| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | +| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | +| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | +| ifs.c:105:8:105:11 | argv | semmle.label | argv | +| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | +| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | +| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | +| ifs.c:111:8:111:11 | argv | semmle.label | argv | +| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | +| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | +| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | +| ifs.c:117:8:117:11 | argv | semmle.label | argv | +| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | +| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | +| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | +| ifs.c:123:8:123:11 | argv | semmle.label | argv | +| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | +| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | +| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | +#select +| ifs.c:62:9:62:10 | c7 | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:61:8:61:11 | argv | argv | +| ifs.c:69:9:69:10 | c8 | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:68:8:68:11 | argv | argv | +| ifs.c:75:9:75:10 | i1 | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:74:8:74:11 | argv | argv | +| ifs.c:81:9:81:10 | i2 | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:80:8:80:11 | argv | argv | +| ifs.c:87:9:87:10 | i3 | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:86:8:86:11 | argv | argv | +| ifs.c:93:9:93:10 | i4 | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:92:8:92:11 | argv | argv | +| ifs.c:99:9:99:10 | i5 | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:98:8:98:11 | argv | argv | +| ifs.c:106:9:106:10 | i6 | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:105:8:105:11 | argv | argv | +| ifs.c:112:9:112:10 | i7 | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:111:8:111:11 | argv | argv | +| ifs.c:118:9:118:10 | i8 | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:117:8:117:11 | argv | argv | +| ifs.c:124:9:124:10 | i9 | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:123:8:123:11 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index f77bf73d52d..d8b49226138 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -1,9 +1,84 @@ -| test.cpp:42:31:42:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:43:31:43:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:45:31:45:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:48:25:48:30 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:49:17:49:30 | new[] | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:52:21:52:27 | call to realloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:127:17:127:22 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:123:25:123:30 | call to getenv | user input (getenv) | +edges +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | (unsigned long)... | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | (unsigned long)... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | +| test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | (size_t)... | +| test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | size | +| test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | size | +nodes +| test.cpp:39:21:39:24 | argv | semmle.label | argv | +| test.cpp:41:38:41:53 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | +| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | +| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | +| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | +| test.cpp:43:38:43:44 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:43:38:43:44 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:43:38:43:44 | tainted | semmle.label | tainted | +| test.cpp:43:38:43:44 | tainted | semmle.label | tainted | +| test.cpp:43:38:43:44 | tainted | semmle.label | tainted | +| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | +| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | +| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | +| test.cpp:43:48:43:63 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | +| test.cpp:44:38:44:47 | call to getTainted | semmle.label | call to getTainted | +| test.cpp:44:38:44:68 | ... * ... | semmle.label | ... * ... | +| test.cpp:44:53:44:68 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | +| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | +| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | +| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | +| test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:48:32:48:35 | size | semmle.label | size | +| test.cpp:48:32:48:35 | size | semmle.label | size | +| test.cpp:48:32:48:35 | size | semmle.label | size | +| test.cpp:49:26:49:29 | size | semmle.label | size | +| test.cpp:49:26:49:29 | size | semmle.label | size | +| test.cpp:49:26:49:29 | size | semmle.label | size | +| test.cpp:52:35:52:50 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | +| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | +| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | +| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | +| test.cpp:52:54:52:60 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:52:54:52:60 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:52:54:52:60 | tainted | semmle.label | tainted | +| test.cpp:52:54:52:60 | tainted | semmle.label | tainted | +| test.cpp:52:54:52:60 | tainted | semmle.label | tainted | +| test.cpp:55:20:55:23 | size | semmle.label | size | +| test.cpp:68:18:68:21 | size | semmle.label | size | +| test.cpp:79:18:79:28 | ... - ... | semmle.label | ... - ... | +| test.cpp:123:25:123:38 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:126:24:126:35 | bounded_size | semmle.label | bounded_size | +| test.cpp:127:24:127:27 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:127:24:127:27 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:127:24:127:27 | size | semmle.label | size | +| test.cpp:127:24:127:27 | size | semmle.label | size | +| test.cpp:127:24:127:27 | size | semmle.label | size | +#select +| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:43:38:43:63 | ... * ... | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:48:25:48:30 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:52:35:52:60 | ... * ... | test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | size | This allocation size is derived from $@ and might overflow | test.cpp:123:25:123:30 | call to getenv | user input (getenv) | From 28319ee0f72275182f7585f88a4b3cb6f115af98 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 1 Apr 2020 12:32:21 -0700 Subject: [PATCH 257/459] Python: ObjectAPI to ValueAPI: SignatureOverriddenMethod: Autoformats --- .../Functions/SignatureOverriddenMethod.ql | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/python/ql/src/Functions/SignatureOverriddenMethod.ql b/python/ql/src/Functions/SignatureOverriddenMethod.ql index e695f2385ea..f24cea3811e 100644 --- a/python/ql/src/Functions/SignatureOverriddenMethod.ql +++ b/python/ql/src/Functions/SignatureOverriddenMethod.ql @@ -16,20 +16,20 @@ import Expressions.CallArgs from FunctionValue base, PythonFunctionValue derived where - not exists(base.getACall()) and - not exists(FunctionValue a_derived | - a_derived.overrides(base) and - exists(a_derived.getACall()) - ) and - not derived.getScope().isSpecialMethod() and - derived.getName() != "__init__" and - derived.isNormalMethod() and - not derived.getScope().isSpecialMethod() and - // call to overrides distributed for efficiency - ( - derived.overrides(base) and derived.minParameters() > base.maxParameters() - or - derived.overrides(base) and derived.maxParameters() < base.minParameters() - ) + not exists(base.getACall()) and + not exists(FunctionValue a_derived | + a_derived.overrides(base) and + exists(a_derived.getACall()) + ) and + not derived.getScope().isSpecialMethod() and + derived.getName() != "__init__" and + derived.isNormalMethod() and + not derived.getScope().isSpecialMethod() and + // call to overrides distributed for efficiency + ( + derived.overrides(base) and derived.minParameters() > base.maxParameters() + or + derived.overrides(base) and derived.maxParameters() < base.minParameters() + ) select derived, "Overriding method '" + derived.getName() + "' has signature mismatch with $@.", - base, "overridden method" + base, "overridden method" From 09349f1957a6a84d13653acaf855a89aafe8ae78 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 1 Apr 2020 12:54:42 -0700 Subject: [PATCH 258/459] Python: ObjectAPI to ValueAPI: ReturnValueIgnored: Autoformats --- python/ql/src/Functions/ReturnValueIgnored.ql | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index 346e9a19d27..95140be3ec3 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -22,7 +22,9 @@ predicate meaningful_return_value(Expr val) { or val instanceof BooleanLiteral or - exists(FunctionValue callee | val = callee.getACall().getNode() and returns_meaningful_value(callee)) + exists(FunctionValue callee | + val = callee.getACall().getNode() and returns_meaningful_value(callee) + ) or not exists(FunctionValue callee | val = callee.getACall().getNode()) and not val instanceof Name } @@ -34,18 +36,22 @@ predicate used_value(Expr val) { ) } -predicate returns_meaningful_value(FunctionValue f) { - not exists(f.getScope().getFallthroughNode()) - and +predicate returns_meaningful_value(FunctionValue f) { + not exists(f.getScope().getFallthroughNode()) and ( - exists(Return ret, Expr val | ret.getScope() = f.getScope() and val = ret.getValue() | - meaningful_return_value(val) and - not used_value(val) - ) - or - /* Is f a builtin function that returns something other than None? - * Ignore __import__ as it is often called purely for side effects */ - f.isBuiltin() and f.(CallableObjectInternal).getAnInferredReturnType() != ClassValue::nonetype() and not f.getName() = "__import__" + exists(Return ret, Expr val | ret.getScope() = f.getScope() and val = ret.getValue() | + meaningful_return_value(val) and + not used_value(val) + ) + or + /* + * Is f a builtin function that returns something other than None? + * Ignore __import__ as it is often called purely for side effects + */ + + f.isBuiltin() and + f.(CallableObjectInternal).getAnInferredReturnType() != ClassValue::nonetype() and + not f.getName() = "__import__" ) } @@ -59,17 +65,19 @@ predicate wrapped_in_try_except(ExprStmt call) { } from ExprStmt call, FunctionValue callee, float percentage_used, int total -where call.getValue() = callee.getACall().getNode() and returns_meaningful_value(callee) and -not wrapped_in_try_except(call) and -exists(int unused | - unused = count(ExprStmt e | e.getValue().getAFlowNode() = callee.getACall()) and - total = count(callee.getACall()) | - percentage_used = (100.0*(total-unused)/total).floor() -) and -/* Report an alert if we see at least 5 calls and the return value is used in at least 3/4 of those calls. */ -percentage_used >= 75 and -total >= 5 - -select call, "Call discards return value of function $@. The result is used in " + percentage_used.toString() + "% of calls.", -callee, callee.getName() - +where + call.getValue() = callee.getACall().getNode() and + returns_meaningful_value(callee) and + not wrapped_in_try_except(call) and + exists(int unused | + unused = count(ExprStmt e | e.getValue().getAFlowNode() = callee.getACall()) and + total = count(callee.getACall()) + | + percentage_used = (100.0 * (total - unused) / total).floor() + ) and + /* Report an alert if we see at least 5 calls and the return value is used in at least 3/4 of those calls. */ + percentage_used >= 75 and + total >= 5 +select call, + "Call discards return value of function $@. The result is used in " + percentage_used.toString() + + "% of calls.", callee, callee.getName() From cc53b15a5d6ec00329f44d07f82319b9536be404 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Wed, 1 Apr 2020 14:41:49 -0700 Subject: [PATCH 259/459] Python: ObjectAPI to ValueAPI: ReturnValueIgnored: Reorganizes predicates --- python/ql/src/Functions/ReturnValueIgnored.ql | 2 +- python/ql/src/semmle/python/objects/Callables.qll | 7 ------- python/ql/src/semmle/python/objects/ObjectAPI.qll | 7 +++++++ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index 95140be3ec3..e6d962e594f 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -50,7 +50,7 @@ predicate returns_meaningful_value(FunctionValue f) { */ f.isBuiltin() and - f.(CallableObjectInternal).getAnInferredReturnType() != ClassValue::nonetype() and + f.getAnInferredReturnType() != ClassValue::nonetype() and not f.getName() = "__import__" ) } diff --git a/python/ql/src/semmle/python/objects/Callables.qll b/python/ql/src/semmle/python/objects/Callables.qll index 010b2c89197..b915e4bd5c2 100644 --- a/python/ql/src/semmle/python/objects/Callables.qll +++ b/python/ql/src/semmle/python/objects/Callables.qll @@ -49,13 +49,6 @@ abstract class CallableObjectInternal extends ObjectInternal { /* Callables aren't iterable */ override ObjectInternal getIterNext() { none() } - - /** Gets a class that this function may return */ - ClassValue getAnInferredReturnType() { - result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType()) - or - result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType()) - } } /** Class representing Python functions */ diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 61e3f17c5d7..66d3950b1ed 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -581,6 +581,13 @@ abstract class FunctionValue extends CallableValue { exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | not origin instanceof Lambda) ) } + + /** Gets a class that this function may return */ + ClassValue getAnInferredReturnType() { + result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType()) + or + result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType()) + } } /** Class representing Python functions */ From 8fdc4b037abe7163e37478d86603702d15f97a94 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 2 Apr 2020 07:30:56 +0200 Subject: [PATCH 260/459] C++: Ensure that no call side effect is an allocation side effect --- .../ir/implementation/raw/internal/TranslatedElement.qll | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 906bb375973..f2b74d03dce 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -443,8 +443,11 @@ newtype TTranslatedElement = TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or // The side effects of a `Call` TTranslatedCallSideEffects(Call expr) { - exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or - expr instanceof ConstructorCall + not expr instanceof AllocationExpr and + ( + exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or + expr instanceof ConstructorCall + ) } or // The side effects of an allocation, i.e. `new`, `new[]` or `malloc` TTranslatedAllocationSideEffects(AllocationExpr expr) or From ca80bfda4f0d493a84d3dbc14a28063577ebca39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20St=C3=B6ckli?= Date: Thu, 2 Apr 2020 07:43:55 +0200 Subject: [PATCH 261/459] Fix tags --- java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp index d0542240daa..dc4c3c161c4 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp @@ -13,7 +13,7 @@ local resources in addition to remote ones.

    When you construct a URL using java.net.URL from a remote source, don't call openStream on it. Instead, use an HTTP Client to fetch the URL and access its content. -You should also validate the URL to check that it uses the correct protocol and host combination.

    +You should also validate the URL to check that it uses the correct protocol and host combination.

    From ead5feb921388305acf20e3621478c0e8c859eac Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 2 Apr 2020 09:50:14 +0100 Subject: [PATCH 262/459] C++: Autoformat. --- .../semmle/code/cpp/models/implementations/Allocation.qll | 6 +++--- .../semmle/code/cpp/models/implementations/Deallocation.qll | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index ad26086998a..c6766983889 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -226,7 +226,8 @@ class OperatorNewAllocationFunction extends AllocationFunction { hasGlobalName(name) and ( // operator new(bytes, ...) - name = "operator new" or + name = "operator new" + or // operator new[](bytes, ...) name = "operator new[]" ) @@ -260,8 +261,7 @@ class CallAllocationExpr extends AllocationExpr, FunctionCall { not ( exists(target.getReallocPtrArg()) and getArgument(target.getSizeArg()).getValue().toInt() = 0 - ) - and + ) and // these are modelled directly (and more accurately), avoid duplication not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this) } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index f94800f657d..d2e4951e436 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -90,7 +90,8 @@ class OperatorDeleteDeallocationFunction extends DeallocationFunction { hasGlobalName(name) and ( // operator delete(pointer, ...) - name = "operator delete" or + name = "operator delete" + or // operator delete[](pointer, ...) name = "operator delete[]" ) From af9e05b9cdbd0e892804e3a75b9b46e92f35bcb2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 2 Apr 2020 10:57:11 +0200 Subject: [PATCH 263/459] C++: Accept test --- .../dataflow/dataflow-tests/test_diff.expected | 4 ---- .../dataflow/dataflow-tests/test_ir.expected | 4 ++++ .../library-tests/dataflow/taint-tests/taint.cpp | 16 ++++++++-------- .../dataflow/taint-tests/test_diff.expected | 12 +++++++++--- .../dataflow/taint-tests/test_ir.expected | 12 ++++++++++++ 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 71630f892f5..8dae5a8dad8 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -31,10 +31,6 @@ | ref.cpp:53:17:53:18 | ref.cpp:62:10:62:11 | AST only | | ref.cpp:53:21:53:22 | ref.cpp:65:10:65:11 | AST only | | ref.cpp:55:23:55:28 | ref.cpp:56:10:56:11 | AST only | -| ref.cpp:94:15:94:20 | ref.cpp:129:13:129:15 | AST only | -| ref.cpp:109:15:109:20 | ref.cpp:132:13:132:15 | AST only | -| ref.cpp:122:23:122:28 | ref.cpp:123:13:123:15 | AST only | -| ref.cpp:125:19:125:24 | ref.cpp:126:13:126:15 | AST only | | test.cpp:75:7:75:8 | test.cpp:76:8:76:9 | AST only | | test.cpp:83:7:83:8 | test.cpp:84:8:84:18 | AST only | | test.cpp:83:7:83:8 | test.cpp:86:8:86:9 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 275cbabc075..202d9827323 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -39,6 +39,10 @@ | globals.cpp:12:10:12:24 | flowTestGlobal1 | globals.cpp:13:23:13:28 | call to source | | globals.cpp:19:10:19:24 | flowTestGlobal2 | globals.cpp:23:23:23:28 | call to source | | lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source | +| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source | +| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source | +| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source | +| ref.cpp:132:13:132:15 | val | ref.cpp:109:15:109:20 | call to source | | test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 5d8327017fa..efcd600e21e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -85,14 +85,14 @@ void class_field_test() { mc1.myMethod(); - sink(mc1.a); - sink(mc1.b); // tainted [NOT DETECTED with IR] - sink(mc1.c); // tainted [NOT DETECTED with IR] - sink(mc1.d); // tainted [NOT DETECTED with IR] - sink(mc2.a); - sink(mc2.b); // tainted [NOT DETECTED with IR] - sink(mc2.c); // tainted [NOT DETECTED with IR] - sink(mc2.d); + sink(mc1.a); // [FALSE POSITIVE] + sink(mc1.b); // tainted + sink(mc1.c); // tainted + sink(mc1.d); // tainted + sink(mc2.a); // [FALSE POSITIVE] + sink(mc2.b); // tainted + sink(mc2.c); // tainted + sink(mc2.d); // [FALSE POSITIVE] } // --- arrays --- 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 329a0bb6ecc..9789a2bda21 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 @@ -11,11 +11,17 @@ | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | +| taint.cpp:88:11:88:11 | taint.cpp:77:7:77:12 | IR only | | taint.cpp:89:11:89:11 | taint.cpp:71:22:71:27 | AST only | +| taint.cpp:89:11:89:11 | taint.cpp:77:7:77:12 | IR only | | taint.cpp:90:11:90:11 | taint.cpp:72:7:72:12 | AST only | -| taint.cpp:91:11:91:11 | taint.cpp:77:7:77:12 | AST only | -| taint.cpp:93:11:93:11 | taint.cpp:71:22:71:27 | AST only | -| taint.cpp:94:11:94:11 | taint.cpp:72:7:72:12 | AST only | +| taint.cpp:90:11:90:11 | taint.cpp:77:7:77:12 | IR only | +| taint.cpp:92:11:92:11 | taint.cpp:71:22:71:27 | IR only | +| taint.cpp:92:11:92:11 | taint.cpp:72:7:72:12 | IR only | +| taint.cpp:93:11:93:11 | taint.cpp:72:7:72:12 | IR only | +| taint.cpp:94:11:94:11 | taint.cpp:71:22:71:27 | IR only | +| taint.cpp:95:11:95:11 | taint.cpp:71:22:71:27 | IR only | +| taint.cpp:95:11:95:11 | taint.cpp:72:7:72:12 | IR only | | taint.cpp:109:7:109:13 | taint.cpp:105:12:105:17 | IR only | | taint.cpp:130:7:130:9 | taint.cpp:127:8:127:13 | IR only | | taint.cpp:137:7:137:9 | taint.cpp:120:11:120:16 | 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 b0107791e61..751775e21ab 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,6 +1,18 @@ | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | +| taint.cpp:88:11:88:11 | a | taint.cpp:77:7:77:12 | call to source | +| taint.cpp:89:11:89:11 | b | taint.cpp:77:7:77:12 | call to source | +| taint.cpp:90:11:90:11 | c | taint.cpp:77:7:77:12 | call to source | +| taint.cpp:91:11:91:11 | d | taint.cpp:77:7:77:12 | call to source | +| taint.cpp:92:11:92:11 | a | taint.cpp:71:22:71:27 | call to source | +| taint.cpp:92:11:92:11 | a | taint.cpp:72:7:72:12 | call to source | +| taint.cpp:93:11:93:11 | b | taint.cpp:71:22:71:27 | call to source | +| taint.cpp:93:11:93:11 | b | taint.cpp:72:7:72:12 | call to source | +| taint.cpp:94:11:94:11 | c | taint.cpp:71:22:71:27 | call to source | +| taint.cpp:94:11:94:11 | c | taint.cpp:72:7:72:12 | call to source | +| taint.cpp:95:11:95:11 | d | taint.cpp:71:22:71:27 | call to source | +| taint.cpp:95:11:95:11 | d | taint.cpp:72:7:72:12 | call to source | | taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source | | taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source | | taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source | From 2d602720c1495f67327c0410ed6e197d4fc76fb5 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Thu, 2 Apr 2020 10:32:12 +0100 Subject: [PATCH 264/459] Docs: Change "handbook" to "reference" --- .../learn-ql/beginner/catch-the-fire-starter.rst | 2 +- .../learn-ql/beginner/crown-the-rightful-heir.rst | 2 +- docs/language/learn-ql/beginner/find-the-thief.rst | 2 +- docs/language/learn-ql/cpp/conversions-classes.rst | 2 +- docs/language/learn-ql/cpp/dataflow.rst | 2 +- docs/language/learn-ql/cpp/expressions-types.rst | 2 +- docs/language/learn-ql/cpp/function-classes.rst | 2 +- docs/language/learn-ql/cpp/introduce-libraries-cpp.rst | 2 +- .../learn-ql/cpp/private-field-initialization.rst | 6 +++--- docs/language/learn-ql/cpp/zero-space-terminator.rst | 2 +- docs/language/learn-ql/csharp/dataflow.rst | 2 +- .../learn-ql/csharp/introduce-libraries-csharp.rst | 2 +- docs/language/learn-ql/go/introduce-libraries-go.rst | 2 +- docs/language/learn-ql/index.rst | 3 +-- docs/language/learn-ql/java/annotations.rst | 2 +- docs/language/learn-ql/java/call-graph.rst | 2 +- docs/language/learn-ql/java/dataflow.rst | 2 +- docs/language/learn-ql/java/expressions-statements.rst | 2 +- docs/language/learn-ql/java/introduce-libraries-java.rst | 2 +- docs/language/learn-ql/java/javadoc.rst | 2 +- docs/language/learn-ql/java/source-locations.rst | 2 +- docs/language/learn-ql/java/types-class-hierarchy.rst | 2 +- docs/language/learn-ql/javascript/dataflow.rst | 2 +- docs/language/learn-ql/javascript/flow-labels.rst | 2 +- .../learn-ql/javascript/introduce-libraries-js.rst | 2 +- .../learn-ql/javascript/introduce-libraries-ts.rst | 2 +- docs/language/learn-ql/javascript/type-tracking.rst | 2 +- .../learn-ql/writing-queries/debugging-queries.rst | 4 ++-- .../learn-ql/writing-queries/introduction-to-queries.rst | 4 ++-- docs/language/ql-handbook/conf.py | 9 +++++---- docs/language/ql-training/cpp/intro-ql-cpp.rst | 2 +- docs/language/ql-training/java/intro-ql-java.rst | 2 +- .../ql-training/slide-snippets/local-data-flow.rst | 4 ++-- docs/language/reusables/python-other-resources.rst | 2 +- 34 files changed, 43 insertions(+), 43 deletions(-) diff --git a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst index e1603303455..f201a628ea0 100644 --- a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -148,5 +148,5 @@ What next? ---------- - Find out who will be the new ruler of the village in the :doc:`next tutorial `. -- Learn more about predicates and classes in the `QL language handbook `__. +- Learn more about predicates and classes in the `QL language reference `__. - Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst index 14978dbd120..69f4a0e135d 100644 --- a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst +++ b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst @@ -161,6 +161,6 @@ You could also try writing more of your own QL queries to find interesting facts What next? ---------- -- Learn more about recursion in the `QL language handbook `__. +- Learn more about recursion in the `QL language reference `__. - Put your QL skills to the test and solve the :doc:`River crossing puzzle `. - Start using QL to analyze projects. See :doc:`Learning CodeQL <../../index>` for a summary of the available languages and resources. diff --git a/docs/language/learn-ql/beginner/find-the-thief.rst b/docs/language/learn-ql/beginner/find-the-thief.rst index 0c168604339..da4037f89ba 100644 --- a/docs/language/learn-ql/beginner/find-the-thief.rst +++ b/docs/language/learn-ql/beginner/find-the-thief.rst @@ -293,5 +293,5 @@ What next? ---------- - Help the villagers track down another criminal in the :doc:`next tutorial `. -- Find out more about the concepts you discovered in this tutorial in the `QL language handbook `__. +- Find out more about the concepts you discovered in this tutorial in the `QL language reference `__. - Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index ec00469091e..553423bb47e 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -226,5 +226,5 @@ Further reading - Explore other ways of querying classes using examples from the `C/C++ cookbook `__. - Take a look at the :doc:`Analyzing data flow in C and C++ ` tutorial. - Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases `, and :doc:`Detecting a potential buffer overflow `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index fe205dd3701..2b12986ce94 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -299,7 +299,7 @@ Further reading --------------- - Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases ` and :doc:`Detecting a potential buffer overflow `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. Answers diff --git a/docs/language/learn-ql/cpp/expressions-types.rst b/docs/language/learn-ql/cpp/expressions-types.rst index a2a3d653c3b..39da25330d3 100644 --- a/docs/language/learn-ql/cpp/expressions-types.rst +++ b/docs/language/learn-ql/cpp/expressions-types.rst @@ -134,5 +134,5 @@ Further reading - Explore other ways of finding types and statements using examples from the C/C++ cookbook for `types `__ and `statements `__. - Take a look at the :doc:`Conversions and classes in C and C++ ` and :doc:`Analyzing data flow in C and C++ ` tutorials. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/function-classes.rst b/docs/language/learn-ql/cpp/function-classes.rst index 3748a3880dc..841add0d4b0 100644 --- a/docs/language/learn-ql/cpp/function-classes.rst +++ b/docs/language/learn-ql/cpp/function-classes.rst @@ -94,5 +94,5 @@ Further reading - Explore other ways of finding functions using examples from the `C/C++ cookbook `__. - Take a look at some other tutorials: :doc:`Expressions, types and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 960c98040fb..69946edec3e 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -524,5 +524,5 @@ Further reading --------------- - Experiment with the worked examples in the CodeQL for C/C++ topics: :doc:`Functions in C and C++ `, :doc:`Expressions, types, and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/private-field-initialization.rst b/docs/language/learn-ql/cpp/private-field-initialization.rst index 5d9e900f4e0..c1f9224a145 100644 --- a/docs/language/learn-ql/cpp/private-field-initialization.rst +++ b/docs/language/learn-ql/cpp/private-field-initialization.rst @@ -102,7 +102,7 @@ You may also wish to consider methods called by constructors that assign to the int m_value; }; -This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls. For more information, see `Recursion `__ in the QL language handbook. +This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls. For more information, see `Recursion `__ in the QL language reference. .. code-block:: ql @@ -126,7 +126,7 @@ This case can be excluded by creating a recursive predicate. The recursive predi Refinement 4—simplifying the query ---------------------------------- -Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see `Transitive closures `__ in the QL language handbook. +Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see `Transitive closures `__ in the QL language reference. .. code-block:: ql @@ -150,5 +150,5 @@ Further reading --------------- - Take a look at another example: :doc:`Detecting a potential buffer overflow `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index 7d1189de3b3..a25437865f7 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -224,5 +224,5 @@ The completed query will now identify cases where the result of ``strlen`` is st Further reading --------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/csharp/dataflow.rst b/docs/language/learn-ql/csharp/dataflow.rst index 7824c1746b5..c4b597428df 100644 --- a/docs/language/learn-ql/csharp/dataflow.rst +++ b/docs/language/learn-ql/csharp/dataflow.rst @@ -550,5 +550,5 @@ Further reading --------------- - Learn about the standard libraries used to write queries for C# in :doc:`Introducing the C# libraries `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index 55611a6c02d..f262478dc44 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1123,5 +1123,5 @@ Further reading --------------- - Visit :doc:`Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/go/introduce-libraries-go.rst b/docs/language/learn-ql/go/introduce-libraries-go.rst index 07f75482d6c..e47ce2b94c4 100644 --- a/docs/language/learn-ql/go/introduce-libraries-go.rst +++ b/docs/language/learn-ql/go/introduce-libraries-go.rst @@ -611,7 +611,7 @@ is to compare them to each other to determine whether two data-flow nodes have t Further reading --------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. .. |ast| image:: ast.png diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 45f257827a5..09ede6c1104 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -38,5 +38,4 @@ CodeQL is based on a powerful query language called QL. The following topics hel Further reading *************** -- `QL language handbook `__: A description of important concepts in QL. -- `QL language specification `__: A formal specification of QL. +- `QL language reference `__: A description of important concepts in QL and a formal specification of the QL language. diff --git a/docs/language/learn-ql/java/annotations.rst b/docs/language/learn-ql/java/annotations.rst index 09588057617..497f20e1ff3 100644 --- a/docs/language/learn-ql/java/annotations.rst +++ b/docs/language/learn-ql/java/annotations.rst @@ -242,4 +242,4 @@ Further reading - Take a look at some of the other articles in this section: :doc:`Javadoc ` and :doc:`Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index bdf713b7372..6f7874c772f 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -166,4 +166,4 @@ Further reading - Find out how to query metadata and white space: :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index ba0b6032dbc..d49128113ba 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -257,7 +257,7 @@ Further reading --------------- - Try the worked examples in these articles: :doc:`Navigating the call graph ` and :doc:`Working with source locations `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. Answers diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index 20954cacd40..24fb943ace5 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -127,4 +127,4 @@ Further reading - Have a look at some of the other articles in this section: :doc:`Java types `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index cba248fd276..8fd21c2d0c2 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -388,4 +388,4 @@ Further reading - Experiment with the worked examples in the CodeQL for Java articles: :doc:`Java types `, :doc:`Overflow-prone comparisons in Java `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc ` and :doc:`Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/javadoc.rst b/docs/language/learn-ql/java/javadoc.rst index 9b26d0c6aae..85981b4bd59 100644 --- a/docs/language/learn-ql/java/javadoc.rst +++ b/docs/language/learn-ql/java/javadoc.rst @@ -223,4 +223,4 @@ Further reading - Find out how you can use the location API to define queries on whitespace: :doc:`Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/source-locations.rst b/docs/language/learn-ql/java/source-locations.rst index da8e8d26836..7d3506b3923 100644 --- a/docs/language/learn-ql/java/source-locations.rst +++ b/docs/language/learn-ql/java/source-locations.rst @@ -187,4 +187,4 @@ Further reading --------------- - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index ac65c539384..3cdafa8389a 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -301,4 +301,4 @@ Further reading - Take a look at some of the other articles in this section: :doc:`Overflow-prone comparisons in Java `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. - Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/javascript/dataflow.rst b/docs/language/learn-ql/javascript/dataflow.rst index 5762e2b2ba6..5009db4756a 100644 --- a/docs/language/learn-ql/javascript/dataflow.rst +++ b/docs/language/learn-ql/javascript/dataflow.rst @@ -467,7 +467,7 @@ Exercise 4: Using the answers from 2 and 3, write a query which finds all global Further reading --------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. - Learn about writing more precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis ` diff --git a/docs/language/learn-ql/javascript/flow-labels.rst b/docs/language/learn-ql/javascript/flow-labels.rst index 8e9881ce12d..ecd8dec6b29 100644 --- a/docs/language/learn-ql/javascript/flow-labels.rst +++ b/docs/language/learn-ql/javascript/flow-labels.rst @@ -399,5 +399,5 @@ Further reading --------------- - Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 81da3135ec3..65b19f2687d 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1032,5 +1032,5 @@ Further reading --------------- - Learn about the standard CodeQL libraries used to write queries for TypeScript in :doc:`CodeQL libraries for TypeScript `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index 6c9cf96bc59..672ea369479 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -450,5 +450,5 @@ Further reading --------------- - Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index 1e73be413c7..d192d98472e 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -521,6 +521,6 @@ Type tracking is used in a few places in the standard libraries: Further reading --------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. - Learn more about the query console in `Using the query console `__ on LGTM.com. - Learn about writing precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis `. diff --git a/docs/language/learn-ql/writing-queries/debugging-queries.rst b/docs/language/learn-ql/writing-queries/debugging-queries.rst index c5fd01c67fc..9eee078d18c 100644 --- a/docs/language/learn-ql/writing-queries/debugging-queries.rst +++ b/docs/language/learn-ql/writing-queries/debugging-queries.rst @@ -11,7 +11,7 @@ Before reading the tips below, it is worth reiterating a few important points ab - CodeQL `predicates `__ and `classes `__ are evaluated to database `tables `__. Large predicates generate large tables with many rows, and are therefore expensive to compute. - The QL language is implemented using standard database operations and `relational algebra `__ (such as join, projection, and union). For further information about query languages and databases, see `About the QL language `__. -- Queries are evaluated *bottom-up*, which means that a predicate is not evaluated until *all* of the predicates that it depends on are evaluated. For more information on query evaluation, see `Evaluation of QL programs `__ in the QL handbook. +- Queries are evaluated *bottom-up*, which means that a predicate is not evaluated until *all* of the predicates that it depends on are evaluated. For more information on query evaluation, see `Evaluation of QL programs `__. Performance tips ---------------- @@ -151,4 +151,4 @@ Now the structure we want is clearer. We've separated out the easy part into its Further information ------------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index c6f30b8075b..43d5e36ffbb 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -23,7 +23,7 @@ You can add custom queries to `custom query packs `__ and in the `Results view `__ in VS Code. -This topic is a basic introduction to query files. You can find more information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language handbook `__ and the `QL language specification `__. +This topic is a basic introduction to query files. You can find more information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language reference `__. For more information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide `__. Basic query structure @@ -97,7 +97,7 @@ From clause =========== The ``from`` clause declares the variables that are used in the query. Each declaration must be of the form `` ``. -For more information on the available `types `__, and to learn how to define your own types using `classes `__, see the `QL language handbook `__. +For more information on the available `types `__, and to learn how to define your own types using `classes `__, see the `QL language reference `__. Where clause ============ diff --git a/docs/language/ql-handbook/conf.py b/docs/language/ql-handbook/conf.py index d1febd209b5..10bda010a7e 100644 --- a/docs/language/ql-handbook/conf.py +++ b/docs/language/ql-handbook/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# QL language handbook build configuration file, created by +# QL language reference build configuration file, created by # sphinx-quickstart on Wed Feb 28 12:01:34 2018. # # This file is execfile()d with the current directory set to its @@ -17,9 +17,10 @@ ################################################################################ # -# Modified 22052019. - -# The configuration values below are specific to the QL handbook +# Modified 02042020 to rename "handbook" to "reference". +# This Sphinx project now contains both the handbook articles and the specifications. +# +# The configuration values below are specific to the QL language reference project. # To amend html_theme_options, update version/release number, or add more sphinx extensions, # refer to code/documentation/ql-documentation/global-sphinx-files/global-conf.py diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 6beff0b708e..7f398da8d4b 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -68,7 +68,7 @@ A simple CodeQL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference `__), see `Introduction to query files `__. In our example here, the first line of the query imports the `CodeQL library for C/C++ `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program. diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index f93a619c142..66c41df44b0 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -68,7 +68,7 @@ A simple CodeQL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference `__), see `Introduction to query files `__. In our example here, the first line of the query imports the `CodeQL library for Java `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program. diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index ed681b0398a..0bbb2c20ba4 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -111,8 +111,8 @@ So all references will need to be qualified (that is, ``DataFlow::Node``) A **module** is a way of organizing QL code by grouping together related predicates, classes, and (sub-)modules. They can be either explicitly declared or implicit. A query library implicitly declares a module with the same name as the QLL file. - For further information on libraries and modules in QL, see the chapter on `Modules `__ in the QL language handbook. - For further information on importing QL libraries and modules, see the chapter on `Name resolution `__ in the QL language handbook. + For further information on libraries and modules in QL, see the chapter on `Modules `__ in the QL language reference. + For further information on importing QL libraries and modules, see the chapter on `Name resolution `__ in the QL language reference. Data flow graph =============== diff --git a/docs/language/reusables/python-other-resources.rst b/docs/language/reusables/python-other-resources.rst index 9668db06d6d..8e9482cf230 100644 --- a/docs/language/reusables/python-other-resources.rst +++ b/docs/language/reusables/python-other-resources.rst @@ -1,3 +1,3 @@ -- "`QL language handbook `__" +- "`QL language reference `__" - `Python cookbook queries `__ in the Semmle wiki - `Python queries in action `__ on LGTM.com From ccce0205b41c61bae00cf4f24f35e947d7ee83af Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 11:33:56 +0100 Subject: [PATCH 265/459] JS: Add test --- .../Expressions/MissingAwait/MissingAwait.expected | 1 + .../ql/test/query-tests/Expressions/MissingAwait/tsTest.ts | 5 +++++ .../test/query-tests/Expressions/MissingAwait/tsconfig.json | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 javascript/ql/test/query-tests/Expressions/MissingAwait/tsTest.ts create mode 100644 javascript/ql/test/query-tests/Expressions/MissingAwait/tsconfig.json diff --git a/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected b/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected index 8c12b4e4f52..02d7d5a668f 100644 --- a/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected +++ b/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected @@ -1,3 +1,4 @@ +| tsTest.ts:4:12:4:19 | cache[x] | Missing await. This value is always a promise. | | tst.js:8:9:8:13 | thing | Missing await. The value 'thing' is always a promise. | | tst.js:10:9:10:13 | thing | Missing await. The value 'thing' is always a promise. | | tst.js:12:15:12:19 | thing | Missing await. The value 'thing' is always a promise. | diff --git a/javascript/ql/test/query-tests/Expressions/MissingAwait/tsTest.ts b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsTest.ts new file mode 100644 index 00000000000..4362c11a8e6 --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsTest.ts @@ -0,0 +1,5 @@ +declare let cache: { [x: string]: Promise }; + +function deleteCache(x: string) { + delete cache[x]; // OK +} diff --git a/javascript/ql/test/query-tests/Expressions/MissingAwait/tsconfig.json b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsconfig.json new file mode 100644 index 00000000000..82194fc7ab0 --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsconfig.json @@ -0,0 +1,3 @@ +{ + "include": ["."] +} From 3a9d047cf59c95d94487c281f819aaf031337b76 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 11:26:04 +0100 Subject: [PATCH 266/459] JS: Ignore delete expressions in js/missing-await --- javascript/ql/src/Expressions/MissingAwait.ql | 3 ++- .../query-tests/Expressions/MissingAwait/MissingAwait.expected | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Expressions/MissingAwait.ql b/javascript/ql/src/Expressions/MissingAwait.ql index be40eef0d4b..e4c092af5c9 100644 --- a/javascript/ql/src/Expressions/MissingAwait.ql +++ b/javascript/ql/src/Expressions/MissingAwait.ql @@ -45,7 +45,8 @@ predicate isBadPromiseContext(Expr expr) { or exists(UnaryExpr e | expr = e.getOperand() and - not e instanceof VoidExpr + not e instanceof VoidExpr and + not e instanceof DeleteExpr ) or expr = any(UpdateExpr e).getOperand() diff --git a/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected b/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected index 02d7d5a668f..8c12b4e4f52 100644 --- a/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected +++ b/javascript/ql/test/query-tests/Expressions/MissingAwait/MissingAwait.expected @@ -1,4 +1,3 @@ -| tsTest.ts:4:12:4:19 | cache[x] | Missing await. This value is always a promise. | | tst.js:8:9:8:13 | thing | Missing await. The value 'thing' is always a promise. | | tst.js:10:9:10:13 | thing | Missing await. The value 'thing' is always a promise. | | tst.js:12:15:12:19 | thing | Missing await. The value 'thing' is always a promise. | From ee106b1103f36f41a9c4669dd507d5e9fc7641b9 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 12:21:10 +0100 Subject: [PATCH 267/459] JS: Remove tautological SourceNode::Range subclasses --- javascript/ql/src/semmle/javascript/frameworks/HTTP.qll | 4 ---- .../ql/src/semmle/javascript/frameworks/LodashUnderscore.qll | 4 ---- 2 files changed, 8 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll index fd28cd43666..6110bb92aca 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll @@ -467,10 +467,6 @@ module HTTP { abstract DataFlow::Node getASecretKey(); } - private class CookieMiddlewareInstanceAsSourceNode extends DataFlow::SourceNode::Range { - CookieMiddlewareInstanceAsSourceNode() { this instanceof CookieMiddlewareInstance } - } - /** * A key used for signed cookies, viewed as a `CryptographicKey`. */ diff --git a/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll index 16c8fd851bf..5461231365f 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll @@ -14,10 +14,6 @@ module LodashUnderscore { abstract string getName(); } - private class MemberAsSourceNode extends DataFlow::SourceNode::Range { - MemberAsSourceNode() { this instanceof Member } - } - /** * An import of `lodash` or `underscore` accessing a given member of that package. */ From 8f930fc3e65c0d9485be0939f469790296a9c41f Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 12:25:33 +0100 Subject: [PATCH 268/459] JS: Remove recursive SourceNode from AngularJS --- .../frameworks/AngularJS/AngularJSCore.qll | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 6eede4a1aa8..09445534253 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -23,14 +23,33 @@ DataFlow::SourceNode angular() { result = DataFlow::moduleImport("angular") } -pragma[noopt] +/** + * Holds if `tl` appears to be a top-level using the AngularJS library. + * + * Should not depend on the `SourceNode` class. + */ +pragma[nomagic] +private predicate isAngularTopLevel(TopLevel tl) { + exists(Import imprt | + imprt.getTopLevel() = tl and + imprt.getImportedPath().getValue() = "angular" + ) + or + exists(GlobalVarAccess global | + global.getName() = "angular" and + global.getTopLevel() = tl + ) +} + +/** + * Holds if `s` is a string in a top-level using the AngularJS library. + * + * Should not depend on the `SourceNode` class. + */ +pragma[nomagic] private predicate isAngularString(Expr s) { - exists(DataFlow::SourceNode angular, StmtContainer sc, TopLevel tl | - angular = angular() and - sc = angular.getContainer() and - tl = sc.getTopLevel() and - tl = s.getTopLevel() - | + isAngularTopLevel(s.getTopLevel()) and + ( s instanceof StringLiteral or s instanceof TemplateLiteral ) From dda3aaa8aaf4c89fe735a534a40566348d656125 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 2 Apr 2020 14:00:33 +0200 Subject: [PATCH 269/459] C++: Add QLDoc to public classes and predicates --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 367d49bb2a7..5eba5108983 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -63,6 +63,14 @@ class Node extends TIRDataFlowNode { */ Variable asVariable() { result = this.(VariableNode).getVariable() } + /** + * Gets the expression that is partially defined by this node, if any. + * + * Partial definitions are created for field stores (`x.y = taint();` is a partial + * definition of `x`), and for calls that may change the value of an object (so + * `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is + * a partial definition of `&x`). + */ Expr asPartialDefinition() { result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression() } @@ -100,6 +108,9 @@ class Node extends TIRDataFlowNode { string toString() { none() } // overridden by subclasses } +/** + * An instruction, viewed as a node in a data flow graph. + */ class InstructionNode extends Node, TInstructionNode { Instruction instr; @@ -146,12 +157,16 @@ class ExprNode extends InstructionNode { override string toString() { result = this.asConvertedExpr().toString() } } +/** + * A node representing a `Parameter`. This includes both explicit parameters such + * as `x` in `f(x)` and implicit parameters such as `this` in `x.f()` + */ class ParameterNode extends InstructionNode { /** * Holds if this node is the parameter of `c` at the specified (zero-based) * position. The implicit `this` parameter is considered to have index `-1`. */ - predicate isParameterOf(Function f, int i) { none() } + predicate isParameterOf(Function f, int i) { none() } // overriden by subclasses } /** @@ -163,6 +178,7 @@ private class ExplicitParameterNode extends ParameterNode { override predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() } + /** Gets the parameter corresponding to this node. */ Parameter getParameter() { result = instr.getParameter() } override string toString() { result = instr.getParameter().toString() } @@ -216,7 +232,25 @@ abstract class PostUpdateNode extends InstructionNode { abstract Node getPreUpdateNode(); } -abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { +/** + * The base class for nodes that perform "partial definitions". + * + * In contrast to a normal "definition", which provides a new value for + * something, a partial definition is an expression that may affect a + * value, but does not necessarily replace it entirely. For example: + * ``` + * x.y = 1; // a partial definition of the object `x`. + * x.y.z = 1; // a partial definition of the object `x.y`. + * x.setY(1); // a partial definition of the object `x`. + * setY(&x); // a partial definition of the object `x`. + * ``` + */ +abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { + /** + * Gets the instruction that partially defines the object. This includes + * both the instruction that partially defines the object, and the chi + * instruction that links up the partial definition to the object. + */ final Instruction getInstructionOrChi() { exists(ChiInstruction chi | not chi.isResultConflated() and @@ -228,7 +262,7 @@ abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructio } } -class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { +private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { override StoreInstruction instr; FieldAddressInstruction field; @@ -310,6 +344,10 @@ class VariableNode extends Node, TVariableNode { */ InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr } +/** + * Gets the `Node` corresponding to a definition by reference of the variable + * that is passed as `argument` of a call. + */ DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e } /** From e2908eaf631519f739545949268bb9a3873ffaa7 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 2 Apr 2020 15:11:13 +0200 Subject: [PATCH 270/459] C++: Add comment explaining why we can split call and allocation side effects --- .../ir/implementation/raw/internal/TranslatedElement.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index f2b74d03dce..c3788f4c8da 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -443,6 +443,12 @@ newtype TTranslatedElement = TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or // The side effects of a `Call` TTranslatedCallSideEffects(Call expr) { + // Exclude allocations such as `malloc` (which happen to also be function calls). + // Both `TranslatedCallSideEffects` and `TranslatedAllocationSideEffects` generate + // the same side effects for its children as they both extend the `TranslatedSideEffects` + // class. + // Note: We can separate allocation side effects and call side effects into two + // translated elements as no call can be both a `ConstructorCall` and an `AllocationExpr`. not expr instanceof AllocationExpr and ( exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or From 26f15b8978465e7ad7f578489e6b83b674af6294 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Thu, 2 Apr 2020 17:16:46 +0100 Subject: [PATCH 271/459] Include "Introduction to QL" in tutorial topic --- .../beginner/catch-the-fire-starter.rst | 4 +- .../beginner/crown-the-rightful-heir.rst | 4 +- .../learn-ql/beginner/find-the-thief.rst | 4 +- .../learn-ql/beginner/ql-tutorials.rst | 6 +- docs/language/learn-ql/index.rst | 1 - docs/language/learn-ql/introduction-to-ql.rst | 60 ++++++++----------- 6 files changed, 34 insertions(+), 45 deletions(-) diff --git a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst index f201a628ea0..72f3f4f7685 100644 --- a/docs/language/learn-ql/beginner/catch-the-fire-starter.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -144,8 +144,8 @@ You can now write a query to select the bald southerners who are allowed into th You have found the two fire starters! They are arrested and the villagers are once again impressed with your work. -What next? ----------- +Further reading +--------------- - Find out who will be the new ruler of the village in the :doc:`next tutorial `. - Learn more about predicates and classes in the `QL language reference `__. diff --git a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst index 69f4a0e135d..df3cd61fde9 100644 --- a/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst +++ b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst @@ -158,8 +158,8 @@ You could also try writing more of your own QL queries to find interesting facts - Do all villagers live in the same region of the village as their parents? - Find out whether there are any time travelers in the village! (Hint: Look for "impossible" family relations.) -What next? ----------- +Further reading +--------------- - Learn more about recursion in the `QL language reference `__. - Put your QL skills to the test and solve the :doc:`River crossing puzzle `. diff --git a/docs/language/learn-ql/beginner/find-the-thief.rst b/docs/language/learn-ql/beginner/find-the-thief.rst index da4037f89ba..02f19cce325 100644 --- a/docs/language/learn-ql/beginner/find-the-thief.rst +++ b/docs/language/learn-ql/beginner/find-the-thief.rst @@ -289,8 +289,8 @@ Have you found the thief? ➤ `See the answer in the query console on LGTM.com `__ -What next? ----------- +Further reading +--------------- - Help the villagers track down another criminal in the :doc:`next tutorial `. - Find out more about the concepts you discovered in this tutorial in the `QL language reference `__. diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index 6585653644d..a8dd35ff617 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -3,17 +3,17 @@ QL tutorials Solve puzzles to learn the basics of QL before you analyze code with CodeQL. The tutorials teach you how to write queries and introduce you to key logic concepts along the way. -Before starting these tutorials, you can read the :doc:`Introduction to QL <../introduction-to-ql>` for a description of the language and some simple examples. - .. toctree:: :hidden: + ../introduction-to-ql find-the-thief catch-the-fire-starter crown-the-rightful-heir cross-the-river -- :doc:`Find the thief `:Take on the role of a detective to find the thief in this fictional village. You will learn how to use logical connectives, quantifiers, and aggregates in QL along the way. +- :doc:`Introduction to QL <../introduction-to-ql>`: Work through some simple exercises and examples to learn about the basics of QL and CodeQL. +- :doc:`Find the thief `: Take on the role of a detective to find the thief in this fictional village. You will learn how to use logical connectives, quantifiers, and aggregates in QL along the way. - :doc:`Catch the fire starter `: Learn about QL predicates and classes to solve your second mystery as a QL detective. - :doc:`Crown the rightful heir `: This is a QL detective puzzle that shows you how to use recursion in QL to write more complex queries. - :doc:`Cross the river `: Use common QL features to write a query that finds a solution to the "River crossing" logic puzzle. diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 09ede6c1104..e5617299436 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -18,7 +18,6 @@ CodeQL is based on a powerful query language called QL. The following topics hel .. toctree:: :maxdepth: 1 - introduction-to-ql beginner/ql-tutorials writing-queries/writing-queries cpp/ql-for-cpp diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index 17db3842749..e154b95fb09 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -1,22 +1,18 @@ Introduction to QL ================== -QL is the powerful query language that underlies CodeQL, which is used to analyze code. -Queries written with CodeQL can find errors and uncover variants of important security vulnerabilities. -Visit `GitHub Security Lab `__ to read about examples of vulnerabilities that we have recently found in open source projects. - -Before diving into code analysis with CodeQL, it can be helpful to learn about the underlying language more generally. - -QL is a logic programming language, so it is built up of logical formulas. QL uses common logical connectives (such as ``and``, ``or``, and ``not``), quantifiers (such as ``forall`` and ``exists``), and other important logical concepts such as predicates. - -QL also supports recursion and aggregates. This allows you to write complex recursive queries using simple QL syntax and directly use aggregates such as ``count``, ``sum``, and ``average``. +Work through some simple exercises to learn about the basics of QL and CodeQL. Basic syntax ------------ The basic syntax of QL will look familiar to anyone who has used SQL, but it is used somewhat differently. -A query is defined by a **select** clause, which specifies what the result of the query should be. You can try out the examples and exercises in this topic directly in LGTM. Open the `query console on LGTM.com `__. Before you can run a query, you need to select a language and project to query (for these logic examples, any language and project will do). +QL is a logic programming language, so it is built up of logical formulas. QL uses common logical connectives (such as ``and``, ``or``, and ``not``), quantifiers (such as ``forall`` and ``exists``), and other important logical concepts such as predicates. + +QL also supports recursion and aggregates. This allows you to write complex recursive queries using simple QL syntax and directly use aggregates such as ``count``, ``sum``, and ``average``. + +You can try out the following examples and exercises using `CodeQL for VS Code `__, or you can run them in the `query console on LGTM.com `__. Before you can run a query on LGTM.com, you need to select a language and project to query (for these logic examples, any language and project will do). Once you have selected a language, the query console is populated with the query: @@ -26,7 +22,7 @@ Once you have selected a language, the query console is populated with the query select "hello world" -This query simply returns the string ``"hello world"``. +This query returns the string ``"hello world"``. More complicated queries typically look like this: @@ -49,14 +45,14 @@ Note that ``int`` specifies that the **type** of ``x`` and ``y`` is 'integer'. T Simple exercises ---------------- -You can try to write simple queries using the some of the basic functions that are available for the ``integer``, ``date``, ``float``, ``boolean`` and ``string`` types. To apply a function, simply append it to the argument. For example, ``1.toString()`` converts the value ``1`` to a string. Notice that as you start typing a function, a pop-up is displayed making it easy to select the function that you want. Also note that you can apply multiple functions in succession. For example, ``100.log().sqrt()`` first takes the natural logarithm of 100 and then computes the square root of the result. +You can try to write simple queries using the some of the basic functions that are available for the ``int``, ``date``, ``float``, ``boolean`` and ``string`` types. To apply a function, append it to the argument. For example, ``1.toString()`` converts the value ``1`` to a string. Notice that as you start typing a function, a pop-up is displayed making it easy to select the function that you want. Also note that you can apply multiple functions in succession. For example, ``100.log().sqrt()`` first takes the natural logarithm of 100 and then computes the square root of the result. Exercise 1 ~~~~~~~~~~ Write a query which returns the length of the string ``"lgtm"``. (Hint: `here `__ is the list of the functions that can be applied to strings.) -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ There is often more than one way to define a query. For example, we can also write the above query in the shorter form: @@ -69,24 +65,24 @@ Exercise 2 Write a query which returns the sine of the minimum of ``3^5`` (``3`` raised to the power ``5``) and ``245.6``. -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ Exercise 3 ~~~~~~~~~~ Write a query which returns the opposite of the boolean ``false``. -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ Exercise 4 ~~~~~~~~~~ Write a query which computes the number of days between June 10 and September 28, 2017. -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ -Example queries ---------------- +Example query with multiple results +----------------------------------- The exercises above all show queries with exactly one result, but in fact many queries have multiple results. For example, the following query computes all `Pythagorean triples `__ between 1 and 10: @@ -114,15 +110,15 @@ To simplify the query, we can introduce a class ``SmallInt`` representing the in ➤ `See this in the query console on LGTM.com `__ -Now that you've seen some general examples, let's use the CodeQL libraries to analyze projects. -In particular, LGTM generates a database representing the code and then CodeQL is used to query this database. For more information, see `Database generation `__ on LGTM.com. +Example CodeQL queries +---------------------- -.. XX: Perhaps a link to the "CodeQL libraries for X"? +The previous examples used the primitive types built in to QL. Although we chose a project to query, they did not use the project-specific database. The following example queries *do* use these databases and give you an idea of how CodeQL is used to analyze projects. -The previous exercises just used the primitive types built in to QL. Although we chose a project to query, they did not use the project-specific database. The following example queries *do* use these databases and give you an idea of what CodeQL can be used for. There are more details about how to use CodeQL `below <#learning-ql>`__, so don't worry if you don't fully understand these examples yet! +Queries using the CodeQL libraries can find errors and uncover variants of important security vulnerabilities in codebases. +Visit `GitHub Security Lab `__ to read about examples of vulnerabilities that we have recently found in open source projects. -Python -~~~~~~ +To import the CodeQL library for a specific programming language, type ``import `` at the start of the query. .. code-block:: ql @@ -132,10 +128,7 @@ Python where count(f.getAnArg()) > 7 select f -➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``f`` representing a function. The ``where`` part limits the functions ``f`` to those with more than 7 arguments. Finally, the ``select`` clause lists these functions. - -JavaScript -~~~~~~~~~~ +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``f`` representing a Python function. The ``where`` part limits the functions ``f`` to those with more than 7 arguments. Finally, the ``select`` clause lists these functions. .. code-block:: ql @@ -145,10 +138,7 @@ JavaScript where c.getText().regexpMatch("(?si).*\\bTODO\\b.*") select c -➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``c`` representing a comment. The ``where`` part limits the comments ``c`` to those containing the word ``"TODO"``. The ``select`` clause lists these comments. - -Java -~~~~ +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``c`` representing a JavaScript comment. The ``where`` part limits the comments ``c`` to those containing the word ``"TODO"``. The ``select`` clause lists these comments. .. code-block:: ql @@ -158,11 +148,11 @@ Java where not exists(p.getAnAccess()) select p -➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``p`` representing a parameter. The ``where`` clause finds unused parameters by limiting the parameters ``p`` to those which are not accessed. Finally, the ``select`` clause lists these parameters. +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``p`` representing a Java parameter. The ``where`` clause finds unused parameters by limiting the parameters ``p`` to those which are not accessed. Finally, the ``select`` clause lists these parameters. -Learning CodeQL +Further reading --------------- - To find out more about how to write your own queries, try working through the :doc:`QL tutorials `. - For an overview of the other available resources, see :doc:`Learning CodeQL <../index>`. -- For a more technical description of the underlying language, see the `QL language reference `__ \ No newline at end of file +- For a more technical description of the underlying language, see the `QL language reference `__. \ No newline at end of file From 712fb8badc00c73e13299b5ab00d86b3c3491910 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 2 Apr 2020 09:19:41 -0700 Subject: [PATCH 272/459] Python: ObjectAPI to ValueAPI: IterReturnsNonSelf: Autoformats --- python/ql/src/Functions/IterReturnsNonSelf.ql | 4 +-- .../src/semmle/python/objects/ObjectAPI.qll | 29 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/python/ql/src/Functions/IterReturnsNonSelf.ql b/python/ql/src/Functions/IterReturnsNonSelf.ql index 35eb9557488..095685b749a 100644 --- a/python/ql/src/Functions/IterReturnsNonSelf.ql +++ b/python/ql/src/Functions/IterReturnsNonSelf.ql @@ -12,9 +12,7 @@ import python -Function iter_method(ClassValue t) { - result = ((FunctionValue)t.lookup("__iter__")).getScope() -} +Function iter_method(ClassValue t) { result = t.lookup("__iter__").(FunctionValue).getScope() } predicate is_self(Name value, Function f) { value.getVariable() = f.getArg(0).(Name).getVariable() } diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index a975cd339a6..2f39d8db16d 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -432,24 +432,27 @@ class ClassValue extends Value { /** Holds if this class is an iterator. */ predicate isIterator() { - this.hasAttribute("__iter__") and - (major_version() = 3 and this.hasAttribute("__next__") - or - /* Because 'next' is a common method name we need to check that an __iter__ - * method actually returns this class. This is not needed for Py3 as the - * '__next__' method exists to define a class as an iterator. - */ - major_version() = 2 and this.hasAttribute("next") and - exists(ClassValue other, FunctionValue iter | - other.declaredAttribute("__iter__") = iter | - iter.getAnInferredReturnType() = this - ) + this.hasAttribute("__iter__") and + ( + major_version() = 3 and this.hasAttribute("__next__") + or + /* + * Because 'next' is a common method name we need to check that an __iter__ + * method actually returns this class. This is not needed for Py3 as the + * '__next__' method exists to define a class as an iterator. + */ + + major_version() = 2 and + this.hasAttribute("next") and + exists(ClassValue other, FunctionValue iter | other.declaredAttribute("__iter__") = iter | + iter.getAnInferredReturnType() = this + ) ) or /* This will be redundant when we have C class information */ this = ClassValue::generator() } - + /** Holds if this class is a container(). That is, does it have a __getitem__ method. */ predicate isContainer() { exists(this.lookup("__getitem__")) } From 69f6790c8305220357bd9e0e5240a10b356b320a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 2 Apr 2020 15:18:33 +0100 Subject: [PATCH 273/459] C++: Add a test of taint through std::strings, based on the one in the old PR. --- .../dataflow/taint-tests/localTaint.expected | 42 +++++++ .../dataflow/taint-tests/stl.cpp | 112 ++++++++++++++++++ .../dataflow/taint-tests/taint.expected | 1 + .../dataflow/taint-tests/test_ir.expected | 2 + 4 files changed, 157 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp 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 648159b4944..26afc08ecbb 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -105,6 +105,48 @@ | format.cpp:130:23:130:23 | 0 | format.cpp:130:21:130:24 | {...} | TAINT | | format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | | | format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | | +| stl.cpp:67:12:67:17 | call to source | stl.cpp:71:7:71:7 | a | | +| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:72:7:72:7 | b | | +| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:74:7:74:7 | b | | +| stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:73:7:73:7 | c | | +| stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:75:7:75:7 | c | | +| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:83:2:83:4 | ss1 | | +| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:89:7:89:9 | ss1 | | +| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:94:7:94:9 | ss1 | | +| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:84:2:84:4 | ss2 | | +| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:90:7:90:9 | ss2 | | +| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:95:7:95:9 | ss2 | | +| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:85:2:85:4 | ss3 | | +| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:91:7:91:9 | ss3 | | +| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:96:7:96:9 | ss3 | | +| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:86:2:86:4 | ss4 | | +| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:92:7:92:9 | ss4 | | +| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:97:7:97:9 | ss4 | | +| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:87:2:87:4 | ss5 | | +| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:93:7:93:9 | ss5 | | +| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:98:7:98:9 | ss5 | | +| stl.cpp:81:16:81:24 | call to basic_string | stl.cpp:87:9:87:9 | t | | +| stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:89:7:89:9 | ss1 | | +| stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:94:7:94:9 | ss1 | | +| stl.cpp:84:2:84:4 | ref arg ss2 | stl.cpp:90:7:90:9 | ss2 | | +| stl.cpp:84:2:84:4 | ref arg ss2 | stl.cpp:95:7:95:9 | ss2 | | +| stl.cpp:85:2:85:4 | ref arg ss3 | stl.cpp:91:7:91:9 | ss3 | | +| stl.cpp:85:2:85:4 | ref arg ss3 | stl.cpp:96:7:96:9 | ss3 | | +| stl.cpp:86:2:86:4 | ref arg ss4 | stl.cpp:92:7:92:9 | ss4 | | +| stl.cpp:86:2:86:4 | ref arg ss4 | stl.cpp:97:7:97:9 | ss4 | | +| stl.cpp:87:2:87:4 | ref arg ss5 | stl.cpp:93:7:93:9 | ss5 | | +| stl.cpp:87:2:87:4 | ref arg ss5 | stl.cpp:98:7:98:9 | ss5 | | +| stl.cpp:101:32:101:37 | source | stl.cpp:106:9:106:14 | source | | +| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:105:2:105:4 | ss1 | | +| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:108:7:108:9 | ss1 | | +| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:110:7:110:9 | ss1 | | +| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:106:2:106:4 | ss2 | | +| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:109:7:109:9 | ss2 | | +| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:111:7:111:9 | ss2 | | +| stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:108:7:108:9 | ss1 | | +| stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:110:7:110:9 | ss1 | | +| stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:109:7:109:9 | ss2 | | +| stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:111:7:111:9 | ss2 | | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp new file mode 100644 index 00000000000..25153b152fe --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -0,0 +1,112 @@ + +typedef unsigned long size_t; + +namespace std +{ + template struct char_traits; + + typedef size_t streamsize; + + 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 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 [NOT DETECTED] + sink(b.c_str()); + sink(c.c_str()); // tainted [NOT DETECTED] +} + +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 46146094e53..ff4ee0d48f0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -8,6 +8,7 @@ | format.cpp:96:8:96:13 | buffer | format.cpp:95:30:95:43 | call to source | | format.cpp:101:8:101:13 | buffer | format.cpp:100:31:100:45 | call to source | | format.cpp:106:8:106:14 | wbuffer | format.cpp:105:38:105:52 | call to source | +| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | 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 b38de345220..5137acf423c 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,3 +1,5 @@ +| stl.cpp:71:7:71:7 | (const char *)... | stl.cpp:67:12:67:17 | call to source | +| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | From b14b52d0ac8a1eca74e3fe10b673ffddb00f6b29 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 24 Jul 2019 17:44:01 +0100 Subject: [PATCH 274/459] C++: Add models for std::string (as in old PR). --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 1 + .../cpp/models/implementations/Strings.qll | 32 +++++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 3 ++ .../dataflow/taint-tests/stl.cpp | 2 +- .../dataflow/taint-tests/taint.expected | 1 + .../dataflow/taint-tests/test_diff.expected | 1 + 6 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 4689cb1c7c8..3dd720b41ab 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -12,4 +12,5 @@ private import implementations.Strcat private import implementations.Strcpy private import implementations.Strdup private import implementations.Strftime +private import implementations.Strings private import implementations.Swap diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll new file mode 100644 index 00000000000..5d82f244af4 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll @@ -0,0 +1,32 @@ +import semmle.code.cpp.models.interfaces.DataFlow +import semmle.code.cpp.models.interfaces.Taint + +/** + * The `std::basic_string` constructor(s). + */ +class StringConstructor extends DataFlowFunction { + StringConstructor() { + this.hasQualifiedName("std", "basic_string", "basic_string") + } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // flow from any constructor argument to return value + input.isInParameter(_) and + output.isOutReturnValue() + } +} + +/** + * The standard function `std::string.c_str`. + */ +class StringCStr extends DataFlowFunction { + StringCStr() { + this.hasQualifiedName("std", "basic_string", "c_str") + } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // flow from string itself (qualifier) to return value + input.isInQualifier() and + output.isOutReturnValue() + } +} 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 26afc08ecbb..d3b07b6f858 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -106,8 +106,10 @@ | format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | | | format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | | | stl.cpp:67:12:67:17 | call to source | stl.cpp:71:7:71:7 | a | | +| stl.cpp:68:16:68:20 | 123 | stl.cpp:68:16:68:21 | call to basic_string | | | stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:72:7:72:7 | b | | | stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:74:7:74:7 | b | | +| stl.cpp:69:16:69:21 | call to source | stl.cpp:69:16:69:24 | call to basic_string | | | stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:73:7:73:7 | c | | | stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:75:7:75:7 | c | | | stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:83:2:83:4 | ss1 | | @@ -125,6 +127,7 @@ | stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:87:2:87:4 | ss5 | | | stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:93:7:93:9 | ss5 | | | stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:98:7:98:9 | ss5 | | +| stl.cpp:81:16:81:21 | call to source | stl.cpp:81:16:81:24 | call to basic_string | | | stl.cpp:81:16:81:24 | call to basic_string | stl.cpp:87:9:87:9 | t | | | stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:89:7:89:9 | ss1 | | | stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:94:7:94:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 25153b152fe..feb574197bb 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -70,7 +70,7 @@ void test_string() sink(a); // tainted sink(b); - sink(c); // tainted [NOT DETECTED] + sink(c); // tainted sink(b.c_str()); sink(c.c_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 ff4ee0d48f0..080021d0986 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -9,6 +9,7 @@ | format.cpp:101:8:101:13 | buffer | format.cpp:100:31:100:45 | call to source | | format.cpp:106:8:106:14 | wbuffer | format.cpp:105:38:105:52 | call to source | | stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | +| stl.cpp:73:7:73:7 | c | stl.cpp:69:16:69:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | 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 7680193da16..6e96d845be3 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 @@ -8,6 +8,7 @@ | format.cpp:96:8:96:13 | format.cpp:95:30:95:43 | AST only | | format.cpp:101:8:101:13 | format.cpp:100:31:100:45 | AST only | | format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | AST only | +| stl.cpp:73:7:73:7 | stl.cpp:69:16:69:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | From 73171682b77d6ec5f46a8bfe8506d8d1df5a79bc Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 2 Apr 2020 19:38:56 +0100 Subject: [PATCH 275/459] C++: Switch to taint flow as suggested in the old PR. --- .../semmle/code/cpp/models/implementations/Strings.qll | 9 ++++----- .../dataflow/taint-tests/localTaint.expected | 8 +++++--- cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp | 2 +- .../library-tests/dataflow/taint-tests/taint.expected | 1 + .../dataflow/taint-tests/test_diff.expected | 1 + 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll index 5d82f244af4..88857208f3d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll @@ -1,15 +1,14 @@ -import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint /** * The `std::basic_string` constructor(s). */ -class StringConstructor extends DataFlowFunction { +class StringConstructor extends TaintFunction { StringConstructor() { this.hasQualifiedName("std", "basic_string", "basic_string") } - override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any constructor argument to return value input.isInParameter(_) and output.isOutReturnValue() @@ -19,12 +18,12 @@ class StringConstructor extends DataFlowFunction { /** * The standard function `std::string.c_str`. */ -class StringCStr extends DataFlowFunction { +class StringCStr extends TaintFunction { StringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") } - override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value input.isInQualifier() and output.isOutReturnValue() 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 d3b07b6f858..3ffd9f30c23 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -106,12 +106,14 @@ | format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | | | format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | | | stl.cpp:67:12:67:17 | call to source | stl.cpp:71:7:71:7 | a | | -| stl.cpp:68:16:68:20 | 123 | stl.cpp:68:16:68:21 | call to basic_string | | +| stl.cpp:68:16:68:20 | 123 | stl.cpp:68:16:68:21 | call to basic_string | TAINT | | stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:72:7:72:7 | b | | | stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:74:7:74:7 | b | | -| stl.cpp:69:16:69:21 | call to source | stl.cpp:69:16:69:24 | call to basic_string | | +| stl.cpp:69:16:69:21 | call to source | stl.cpp:69:16:69:24 | call to basic_string | TAINT | | stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:73:7:73:7 | c | | | stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:75:7:75:7 | c | | +| stl.cpp:74:7:74:7 | b | stl.cpp:74:9:74:13 | call to c_str | TAINT | +| stl.cpp:75:7:75:7 | c | stl.cpp:75:9:75:13 | call to c_str | TAINT | | stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:83:2:83:4 | ss1 | | | stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:89:7:89:9 | ss1 | | | stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:94:7:94:9 | ss1 | | @@ -127,7 +129,7 @@ | stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:87:2:87:4 | ss5 | | | stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:93:7:93:9 | ss5 | | | stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:98:7:98:9 | ss5 | | -| stl.cpp:81:16:81:21 | call to source | stl.cpp:81:16:81:24 | call to basic_string | | +| stl.cpp:81:16:81:21 | call to source | stl.cpp:81:16:81:24 | call to basic_string | TAINT | | stl.cpp:81:16:81:24 | call to basic_string | stl.cpp:87:9:87:9 | t | | | stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:89:7:89:9 | ss1 | | | stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:94:7:94:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index feb574197bb..54755871f6a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -72,7 +72,7 @@ void test_string() sink(b); sink(c); // tainted sink(b.c_str()); - sink(c.c_str()); // tainted [NOT DETECTED] + sink(c.c_str()); // tainted } void test_stringstream() 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 080021d0986..a1c10d688fd 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -10,6 +10,7 @@ | format.cpp:106:8:106:14 | wbuffer | format.cpp:105:38:105:52 | call to source | | stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | | stl.cpp:73:7:73:7 | c | stl.cpp:69:16:69:21 | call to source | +| stl.cpp:75:9:75:13 | call to c_str | stl.cpp:69:16:69:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | 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 6e96d845be3..9eb40b4271b 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 @@ -9,6 +9,7 @@ | format.cpp:101:8:101:13 | format.cpp:100:31:100:45 | AST only | | format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | AST only | | stl.cpp:73:7:73:7 | stl.cpp:69:16:69:21 | AST only | +| stl.cpp:75:9:75:13 | stl.cpp:69:16:69:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | From ab716ebe754f99a9b94a9ff97ba5fc626a1d96bb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 2 Apr 2020 19:41:05 +0100 Subject: [PATCH 276/459] C++: Change note. --- change-notes/1.24/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.24/analysis-cpp.md b/change-notes/1.24/analysis-cpp.md index 75e37d43ead..0d6479c902e 100644 --- a/change-notes/1.24/analysis-cpp.md +++ b/change-notes/1.24/analysis-cpp.md @@ -45,6 +45,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. `StackVariableReachability`. The functionality is the same. * The models library models `strlen` in more detail, and includes common variations such as `wcslen`. * The models library models `gets` and similar functions. +* The models library now partially models `std::string`. * The taint tracking library (`semmle.code.cpp.dataflow.TaintTracking`) has had the following improvements: * The library now models data flow through `strdup` and similar functions. From e9132d833c957d2c4dc46066dc844f69bb3b5496 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 2 Apr 2020 19:41:25 +0100 Subject: [PATCH 277/459] C++: Autoformat. --- .../semmle/code/cpp/models/implementations/Strings.qll | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll index 88857208f3d..0148c8e6342 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll @@ -4,9 +4,7 @@ import semmle.code.cpp.models.interfaces.Taint * The `std::basic_string` constructor(s). */ class StringConstructor extends TaintFunction { - StringConstructor() { - this.hasQualifiedName("std", "basic_string", "basic_string") - } + StringConstructor() { this.hasQualifiedName("std", "basic_string", "basic_string") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any constructor argument to return value @@ -19,9 +17,7 @@ class StringConstructor extends TaintFunction { * The standard function `std::string.c_str`. */ class StringCStr extends TaintFunction { - StringCStr() { - this.hasQualifiedName("std", "basic_string", "c_str") - } + StringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value From c9ec30fa2aac06685ebdb0109747ee611f58dd77 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 2 Apr 2020 19:42:17 +0100 Subject: [PATCH 278/459] C++: Update use of deprecated methods. --- .../semmle/code/cpp/models/implementations/Strings.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll index 0148c8e6342..e9630050f74 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll @@ -8,8 +8,8 @@ class StringConstructor extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any constructor argument to return value - input.isInParameter(_) and - output.isOutReturnValue() + input.isParameter(_) and + output.isReturnValue() } } @@ -21,7 +21,7 @@ class StringCStr extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value - input.isInQualifier() and - output.isOutReturnValue() + input.isQualifierObject() and + output.isReturnValue() } } From 9481fada510f714397d9fe9c7019ddaae3cd9a47 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Thu, 2 Apr 2020 20:29:45 +0100 Subject: [PATCH 279/459] C#: Address review comments. --- .../BuildAnalysis.cs | 112 ++++++++++-------- .../CsProjFile.cs | 55 ++++----- .../DotNet.cs | 29 +---- .../NugetPackages.cs | 54 +-------- .../Program.cs | 12 +- .../ProgressMonitor.cs | 2 +- ...Semmle.Extraction.CSharp.Standalone.csproj | 1 + 7 files changed, 94 insertions(+), 171 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs index cdbc0315726..2894222ca89 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs @@ -1,9 +1,13 @@ -using System; +using Semmle.Util; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using Semmle.Extraction.CSharp.Standalone; using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Text; +using System.Security.Cryptography; namespace Semmle.BuildAnalyser { @@ -42,20 +46,18 @@ namespace Semmle.BuildAnalyser /// /// Main implementation of the build analysis. /// - class BuildAnalysis : IBuildAnalysis + class BuildAnalysis : IBuildAnalysis, IDisposable { private readonly AssemblyCache assemblyCache; private readonly NugetPackages nuget; private readonly IProgressMonitor progressMonitor; - private HashSet usedReferences = new HashSet(); - private readonly HashSet usedSources = new HashSet(); - private readonly HashSet missingSources = new HashSet(); - private readonly Dictionary unresolvedReferences = new Dictionary(); + private readonly IDictionary usedReferences = new ConcurrentDictionary(); + private readonly IDictionary sources = new ConcurrentDictionary(); + private readonly IDictionary unresolvedReferences = new ConcurrentDictionary(); private readonly DirectoryInfo sourceDir; private int failedProjects, succeededProjects; private readonly string[] allSources; private int conflictedReferences = 0; - private readonly object mutex = new object(); ///
    class TupleType : Type { - public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntity(cx, type); + public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntityFromSymbol(cx, type); class TupleTypeFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index 7d9f5e3651e..857d3def945 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -324,6 +324,14 @@ namespace Semmle.Extraction.CSharp.Entities } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel; + + public override bool Equals(object obj) + { + var other = obj as Type; + return other?.GetType() == GetType() && SymbolEqualityComparer.IncludeNullability.Equals(other.symbol, symbol); + } + + public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(symbol); } abstract class Type : Type where T : ITypeSymbol diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs index 2fdb8cd3a83..2c7c6373143 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs @@ -88,7 +88,7 @@ namespace Semmle.Extraction.CSharp.Entities } static public TypeParameter Create(Context cx, ITypeParameterSymbol p) => - TypeParameterFactory.Instance.CreateEntity(cx, p); + TypeParameterFactory.Instance.CreateEntityFromSymbol(cx, p); /// /// The variance of this type parameter. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs index 9c94058af1f..a66ae7cb1e8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs @@ -190,7 +190,7 @@ namespace Semmle.Extraction.CSharp.Entities return result; } - public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntity(cx, symbol); + public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class UserOperatorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index 918642f198d..7d860dabc69 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -51,7 +51,18 @@ namespace Semmle.Extraction /// The new/existing entity. public Entity CreateEntity(ICachedEntityFactory factory, Type init) where Entity : ICachedEntity { - return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init); + return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init, objectEntityCache); + } + + /// + /// Creates a new entity using the factory. + /// + /// The entity factory. + /// The initializer for the entity. + /// The new/existing entity. + public Entity CreateEntityFromSymbol(ICachedEntityFactory factory, Type init) where Entity : ICachedEntity + { + return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init, symbolEntityCache); } // A recursion guard against writing to the trap file whilst writing an id to the trap file. @@ -136,8 +147,12 @@ namespace Semmle.Extraction public Label GetNewLabel() => new Label(GetNewId()); private Entity CreateNonNullEntity(ICachedEntityFactory factory, Type init) where Entity : ICachedEntity + => CreateNonNullEntity(factory, init, objectEntityCache); + + + private Entity CreateNonNullEntity(ICachedEntityFactory factory, Type init, IDictionary dictionary) where Entity : ICachedEntity { - if (objectEntityCache.TryGetValue(init, out var cached)) + if (dictionary.TryGetValue(init, out var cached)) return (Entity)cached; using (StackGuard) @@ -146,7 +161,7 @@ namespace Semmle.Extraction var entity = factory.Create(this, init); entity.Label = label; - objectEntityCache[init] = entity; + dictionary[init] = entity; DefineLabel(entity, TrapWriter.Writer, Extractor); if (entity.NeedsPopulation) @@ -200,7 +215,17 @@ namespace Semmle.Extraction #if DEBUG_LABELS readonly Dictionary idLabelCache = new Dictionary(); #endif - readonly Dictionary objectEntityCache = new Dictionary(); + class SymbolComparer : IEqualityComparer + { + IEqualityComparer comparer = SymbolEqualityComparer.IncludeNullability; + + bool IEqualityComparer.Equals(object x, object y) => comparer.Equals((ISymbol)x, (ISymbol)y); + + int IEqualityComparer.GetHashCode(object obj) => comparer.GetHashCode((ISymbol)obj); + } + + readonly IDictionary objectEntityCache = new Dictionary(); + readonly IDictionary symbolEntityCache = new Dictionary(10000, new SymbolComparer()); readonly Dictionary entityLabelCache = new Dictionary(); readonly HashSet
    /// Performs a C# build analysis. @@ -77,7 +79,7 @@ namespace Semmle.BuildAnalyser ToArray(); var dllDirNames = options.DllDirs.Select(Path.GetFullPath).ToList(); - PackageDirectory = TemporaryDirectory.CreateTempDirectory(sourceDir.FullName); + PackageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName)); if (options.UseNuGet) { @@ -97,23 +99,22 @@ namespace Semmle.BuildAnalyser { dllDirNames.Add(Runtime.Runtimes.First()); } - + + // These files can sometimes prevent `dotnet restore` from working correctly. + using (new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories))) + using (new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories))) { - // These files can sometimes prevent `dotnet restore` from working correctly. - using (new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories))) - using (new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories))) - { - var solutions = options.SolutionFile != null ? - new[] { options.SolutionFile } : - sourceDir.GetFiles("*.sln", SearchOption.AllDirectories).Select(d => d.FullName); + var solutions = options.SolutionFile != null ? + new[] { options.SolutionFile } : + sourceDir.GetFiles("*.sln", SearchOption.AllDirectories).Select(d => d.FullName); - RestoreSolutions(solutions); - dllDirNames.Add(PackageDirectory.DirInfo.FullName); - assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); - AnalyseSolutions(solutions); + RestoreSolutions(solutions); + dllDirNames.Add(PackageDirectory.DirInfo.FullName); + assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); + AnalyseSolutions(solutions); - usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); - } + foreach (var filename in assemblyCache.AllAssemblies.Select(a => a.Filename)) + UseReference(filename); } ResolveConflicts(); @@ -124,7 +125,7 @@ namespace Semmle.BuildAnalyser } // Output the findings - foreach (var r in usedReferences) + foreach (var r in usedReferences.Keys) { progressMonitor.ResolvedReference(r); } @@ -146,6 +147,25 @@ namespace Semmle.BuildAnalyser DateTime.Now - startTime); } + /// + /// Computes a unique temp directory for the packages associated + /// with this source tree. Use a SHA1 of the directory name. + /// + /// + /// The full path of the temp directory. + private static string ComputeTempDirectory(string srcDir) + { + var bytes = Encoding.Unicode.GetBytes(srcDir); + + using var sha1 = new SHA1CryptoServiceProvider(); + var sha = sha1.ComputeHash(bytes); + var sb = new StringBuilder(); + foreach (var b in sha.Take(8)) + sb.AppendFormat("{0:x2}", b); + + return Path.Combine(Path.GetTempPath(), "GitHub", "packages", sb.ToString()); + } + /// /// Resolves conflicts between all of the resolved references. /// If the same assembly name is duplicated with different versions, @@ -154,7 +174,7 @@ namespace Semmle.BuildAnalyser void ResolveConflicts() { var sortedReferences = usedReferences. - Select(r => assemblyCache.GetAssemblyInfo(r)). + Select(r => assemblyCache.GetAssemblyInfo(r.Key)). OrderBy(r => r.Version). ToArray(); @@ -165,7 +185,9 @@ namespace Semmle.BuildAnalyser finalAssemblyList[r.Name] = r; // Update the used references list - usedReferences = new HashSet(finalAssemblyList.Select(r => r.Value.Filename)); + usedReferences.Clear(); + foreach (var r in finalAssemblyList.Select(r => r.Value.Filename)) + UseReference(r); // Report the results foreach (var r in sortedReferences) @@ -194,8 +216,7 @@ namespace Semmle.BuildAnalyser /// The filename of the reference. void UseReference(string reference) { - lock (mutex) - usedReferences.Add(reference); + usedReferences[reference] = true; } /// @@ -204,27 +225,18 @@ namespace Semmle.BuildAnalyser /// The source file. void UseSource(FileInfo sourceFile) { - if (sourceFile.Exists) - { - lock(mutex) - usedSources.Add(sourceFile.FullName); - } - else - { - lock(mutex) - missingSources.Add(sourceFile.FullName); - } + sources[sourceFile.FullName] = sourceFile.Exists; } /// /// The list of resolved reference files. /// - public IEnumerable ReferenceFiles => this.usedReferences; + public IEnumerable ReferenceFiles => this.usedReferences.Keys; /// /// The list of source files used in projects. /// - public IEnumerable ProjectSourceFiles => usedSources; + public IEnumerable ProjectSourceFiles => sources.Where(s => s.Value).Select(s => s.Key); /// /// All of the source files in the source directory. @@ -240,7 +252,7 @@ namespace Semmle.BuildAnalyser /// List of source files which were mentioned in project files but /// do not exist on the file system. /// - public IEnumerable MissingSourceFiles => missingSources; + public IEnumerable MissingSourceFiles => sources.Where(s => !s.Value).Select(s => s.Key); /// /// Record that a particular reference couldn't be resolved. @@ -250,8 +262,7 @@ namespace Semmle.BuildAnalyser /// The project file making the reference. void UnresolvedReference(string id, string projectFile) { - lock(mutex) - unresolvedReferences[id] = projectFile; + unresolvedReferences[id] = projectFile; } readonly TemporaryDirectory PackageDirectory; @@ -276,7 +287,7 @@ namespace Semmle.BuildAnalyser try { - IProjectFile csProj = new CsProjFile(project); + var csProj = new CsProjFile(project); foreach (var @ref in csProj.References) { @@ -309,14 +320,6 @@ namespace Semmle.BuildAnalyser } - /// - /// Delete packages directory. - /// - public void Cleanup() - { - PackageDirectory?.Cleanup(); - } - void Restore(string projectOrSolution) { int exit = DotNet.RestoreToDirectory(projectOrSolution, PackageDirectory.DirInfo.FullName); @@ -345,7 +348,7 @@ namespace Semmle.BuildAnalyser { var sln = new SolutionFile(solutionFile); progressMonitor.AnalysingSolution(solutionFile); - AnalyseProjectFiles(sln.Projects.Select(p => new FileInfo(p)).Where(p => p.Exists).ToArray()); + AnalyseProjectFiles(sln.Projects.Select(p => new FileInfo(p)).Where(p => p.Exists)); } catch (Microsoft.Build.Exceptions.InvalidProjectFileException ex) { @@ -353,5 +356,10 @@ namespace Semmle.BuildAnalyser } }); } + + public void Dispose() + { + PackageDirectory?.Dispose(); + } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs index fc7972b6169..1083c9b6257 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs @@ -5,21 +5,14 @@ using System.Xml; namespace Semmle.BuildAnalyser { - interface IProjectFile - { - IEnumerable References { get; } - - IEnumerable Sources { get; } - } - /// /// Represents a .csproj file and reads information from it. /// - class CsProjFile : IProjectFile + class CsProjFile { - public string Filename { get; } + private string Filename { get; } - public string Directory => Path.GetDirectoryName(Filename); + private string Directory => Path.GetDirectoryName(Filename); /// /// Reads the .csproj file. @@ -52,7 +45,7 @@ namespace Semmle.BuildAnalyser /// and there seems to be no way to make it succeed. Fails on Linux. /// /// The file to read. - public void ReadMsBuildProject(FileInfo filename) + private void ReadMsBuildProject(FileInfo filename) { var msbuildProject = new Microsoft.Build.Execution.ProjectInstance(filename.FullName); @@ -75,7 +68,7 @@ namespace Semmle.BuildAnalyser /// fallback if ReadMsBuildProject() fails. /// /// The .csproj file. - public void ReadProjectFileAsXml(FileInfo filename) + private void ReadProjectFileAsXml(FileInfo filename) { var projFile = new XmlDocument(); var mgr = new XmlNamespaceManager(projFile.NameTable); @@ -88,15 +81,15 @@ namespace Semmle.BuildAnalyser bool netCoreProjectFile = root.GetAttribute("Sdk") == "Microsoft.NET.Sdk"; - if(netCoreProjectFile) + if (netCoreProjectFile) { - var relativeCsIncludes2 = + var relativeCsIncludes = root.SelectNodes("/Project/ItemGroup/Compile/@Include", mgr). NodeList(). Select(node => node.Value). ToArray(); - var explicitCsFiles = relativeCsIncludes2. + var explicitCsFiles = relativeCsIncludes. Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs). Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))); @@ -105,25 +98,27 @@ namespace Semmle.BuildAnalyser csFiles = explicitCsFiles.Concat(additionalCsFiles).ToArray(); references = new string[0]; - return; } + else + { - references = - root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Reference/@Include", mgr). - NodeList(). - Select(node => node.Value). - ToArray(); + references = + root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Reference/@Include", mgr). + NodeList(). + Select(node => node.Value). + ToArray(); - var relativeCsIncludes = - root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Compile/@Include", mgr). - NodeList(). - Select(node => node.Value). - ToArray(); + var relativeCsIncludes = + root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Compile/@Include", mgr). + NodeList(). + Select(node => node.Value). + ToArray(); - csFiles = relativeCsIncludes. - Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs). - Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))). - ToArray(); + csFiles = relativeCsIncludes. + Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs). + Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))). + ToArray(); + } } string[] references; diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs index 299770a47e1..6edd217af8d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs @@ -13,36 +13,9 @@ namespace Semmle.BuildAnalyser { public static int RestoreToDirectory(string projectOrSolutionFile, string packageDirectory) { - using var proc = Process.Start("dotnet", $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\""); + using var proc = Process.Start("dotnet", $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\" /p:DisableImplicitNuGetFallbackFolder=true"); proc.WaitForExit(); return proc.ExitCode; } } - - /// - /// Utility to temporarily rename a set of files. - /// - sealed class FileRenamer : IDisposable - { - readonly string[] files; - const string suffix = ".codeqlhidden"; - - public FileRenamer(IEnumerable oldFiles) - { - files = oldFiles.Select(f => f.FullName).ToArray(); - - foreach(var file in files) - { - File.Move(file, file + suffix); - } - } - - public void Dispose() - { - foreach (var file in files) - { - File.Move(file + suffix, file); - } - } - } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs index ddb744ab4f7..2ea3afb6c69 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs @@ -1,10 +1,9 @@ -using System; +using Semmle.Util; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Security.Cryptography; -using System.Text; namespace Semmle.BuildAnalyser { @@ -134,53 +133,4 @@ namespace Semmle.BuildAnalyser readonly string nugetExe; } - - /// - /// A temporary directory that is created within the system temp directory. - /// When this object is disposed, the directory is deleted. - /// - sealed class TemporaryDirectory : IDisposable - { - public DirectoryInfo DirInfo { get; } - - public TemporaryDirectory(string name) - { - DirInfo = new DirectoryInfo(name); - DirInfo.Create(); - } - - /// - /// Computes a unique temp directory for the packages associated - /// with this source tree. Use a SHA1 of the directory name. - /// - /// - /// The full path of the temp directory. - public static string ComputeTempDirectory(string srcDir) - { - var bytes = Encoding.Unicode.GetBytes(srcDir); - - using var sha1 = new SHA1CryptoServiceProvider(); - var sha = sha1.ComputeHash(bytes); - var sb = new StringBuilder(); - foreach (var b in sha.Take(8)) - sb.AppendFormat("{0:x2}", b); - - return Path.Combine(Path.GetTempPath(), "GitHub", "packages", sb.ToString()); - } - - public static TemporaryDirectory CreateTempDirectory(string source) => new TemporaryDirectory(ComputeTempDirectory(source)); - - public void Cleanup() - { - DirInfo.Delete(true); - } - - public void Dispose() - { - Cleanup(); - } - - public override string ToString() => DirInfo.FullName.ToString(); - } - } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs index 2dc6e2cd287..106771faef2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs @@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Standalone /// /// Searches for source/references and creates separate extractions. /// - class Analysis + class Analysis : IDisposable { readonly ILogger logger; @@ -71,12 +71,9 @@ namespace Semmle.Extraction.CSharp.Standalone projectExtraction.Sources.AddRange(options.SolutionFile == null ? buildAnalysis.AllSourceFiles : buildAnalysis.ProjectSourceFiles); } - /// - /// Delete any Nuget assemblies. - /// - public void Cleanup() + public void Dispose() { - buildAnalysis.Cleanup(); + buildAnalysis.Dispose(); } }; @@ -87,7 +84,7 @@ namespace Semmle.Extraction.CSharp.Standalone var options = Options.Create(args); // options.CIL = true; // To do: Enable this var output = new ConsoleLogger(options.Verbosity); - var a = new Analysis(output); + using var a = new Analysis(output); if (options.Help) { @@ -123,7 +120,6 @@ namespace Semmle.Extraction.CSharp.Standalone output.Log(Severity.Info, $"Extraction completed in {DateTime.Now-start}"); } - a.Cleanup(); return 0; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs index 03815f7f710..5bbe1e3a5b2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs @@ -51,7 +51,7 @@ namespace Semmle.BuildAnalyser public void AnalysingSolution(string filename) { - logger.Log(Severity.Info, $"Analysing {filename}..."); + logger.Log(Severity.Info, $"Analyzing {filename}..."); } public void FailedProjectFile(string filename, string reason) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj index b8c27e49e8d..f9efd0d9ebb 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj @@ -14,6 +14,7 @@ + From fd915bb5b1c6fabfd65623bb406d9d0600c48ed2 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 2 Apr 2020 14:56:11 -0700 Subject: [PATCH 280/459] C++: fix join order in IR virtual dispatch --- .../cpp/ir/dataflow/internal/DataFlowDispatch.qll | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index abb62b9a021..55378ed36ef 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -70,8 +70,7 @@ private module VirtualDispatch { // Call return exists(DataFlowCall call, ReturnKind returnKind | other = getAnOutNode(call, returnKind) and - src.(ReturnNode).getKind() = returnKind and - call.getStaticCallTarget() = src.getEnclosingCallable() + returnNodeWithKindAndEnclosingCallable(src, returnKind, call.getStaticCallTarget()) ) and allowFromArg = false or @@ -125,6 +124,16 @@ private module VirtualDispatch { } } + /** + * A ReturnNode with its ReturnKind and its enclosing callable. + * + * Used to fix a join ordering issue in flowsFrom. + */ + private predicate returnNodeWithKindAndEnclosingCallable(ReturnNode node, ReturnKind kind, DataFlowCallable callable) { + node.getKind() = kind and + node.getEnclosingCallable() = callable + } + /** Call through a function pointer. */ private class DataSensitiveExprCall extends DataSensitiveCall { DataSensitiveExprCall() { not exists(this.getStaticCallTarget()) } From 3804d3fcfdaeed6c2ecb6b250ae1f6561fc00e32 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 13:21:34 +0100 Subject: [PATCH 281/459] JS: Remove Import->SourceNode dependency from lazy cache --- .../javascript/frameworks/LazyCache.qll | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll index b8c1c1e0c1f..0477c14acac 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll @@ -6,8 +6,11 @@ import javascript module LazyCache { /** + * DEPRECATED. DO NOT USE. + * * A lazy-cache object, usually created through an expression of form `require('lazy-cache')(require)`. */ + deprecated class LazyCacheObject extends DataFlow::SourceNode { LazyCacheObject() { // Use `require` directly instead of `moduleImport` to avoid recursion. @@ -19,13 +22,26 @@ module LazyCache { } } + /** + * A variable containing a lazy-cache object. + */ + class LazyCacheVariable extends LocalVariable { + LazyCacheVariable() { + // To avoid recursion, this should not depend on `SourceNode`. + exists(Require req | + req.getArgument(0).getStringValue() = "lazy-cache" and + getAnAssignedExpr().(CallExpr).getCallee() = req + ) + } + } + /** * An import through `lazy-cache`. */ class LazyCacheImport extends CallExpr, Import { - LazyCacheObject cache; + LazyCacheVariable cache; - LazyCacheImport() { this = cache.getACall().asExpr() } + LazyCacheImport() { getCallee() = cache.getAnAccess() } /** Gets the name of the package as it's exposed on the lazy-cache object. */ string getLocalAlias() { @@ -39,10 +55,23 @@ module LazyCache { override PathExpr getImportedPath() { result = getArgument(0) } + private LazyCacheVariable getVariable() { + result = cache + } + + pragma[noopt] override DataFlow::Node getImportedModuleNode() { + this instanceof LazyCacheImport and result = this.flow() or - result = cache.getAPropertyRead(getLocalAlias()) + exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName | + variable = getVariable() and + base = variable.getAnAccess() and + access.getBase() = base and + localName = getLocalAlias() and + access.getPropertyName() = localName and + result = access.flow() + ) } } From 346867f42574381c73e1f4da67b73ee58c68608c Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 15:30:17 +0100 Subject: [PATCH 282/459] JS: Remove Import->SourceNode dependency from AMD --- javascript/ql/src/semmle/javascript/AMD.qll | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll index 38d049c088d..2beee7f6ce9 100644 --- a/javascript/ql/src/semmle/javascript/AMD.qll +++ b/javascript/ql/src/semmle/javascript/AMD.qll @@ -56,10 +56,16 @@ class AmdModuleDefinition extends CallExpr { */ pragma[nomagic] DataFlow::SourceNode getFactoryNode() { - result.flowsToExpr(getLastArgument()) and + result = getFactoryNodeInternal() and result instanceof DataFlow::ValueNode } + private + DataFlow::Node getFactoryNodeInternal() { + result = DataFlow::valueNode(getLastArgument()) or + result = getFactoryNodeInternal().getAPredecessor() + } + /** Gets the expression defining this module. */ Expr getModuleExpr() { exists(DataFlow::Node f | f = getFactoryNode() | @@ -108,7 +114,7 @@ class AmdModuleDefinition extends CallExpr { * Gets the `i`th parameter of the factory function of this module. */ private SimpleParameter getFactoryParameter(int i) { - getFactoryNode().(DataFlow::FunctionNode).getParameter(i) = DataFlow::parameterNode(result) + getFactoryNodeInternal().asExpr().(Function).getParameter(i) = result } /** From 93971e943342dd606fda9a97f26b86fc5aad953e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 15:30:33 +0100 Subject: [PATCH 283/459] JS: Make local flow not depend on SourceNode --- javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 5d7ce03e467..d7bf1e304ea 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -1369,18 +1369,18 @@ module DataFlow { */ private predicate lvalueDefaultFlowStep(Node pred, Node succ) { exists(PropertyPattern pattern | - pred = valueNode(pattern.getDefault()) and + pred = TValueNode(pattern.getDefault()) and succ = lvalueNode(pattern.getValuePattern()) ) or exists(ArrayPattern array, int i | - pred = valueNode(array.getDefault(i)) and + pred = TValueNode(array.getDefault(i)) and succ = lvalueNode(array.getElement(i)) ) or exists(Parameter param | - pred = valueNode(param.getDefault()) and - succ = parameterNode(param) + pred = TValueNode(param.getDefault()) and + parameterNode(succ, param) ) } From ffbbdd777974d61797c78ea0e99aa56a125fd056 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 23:04:24 +0100 Subject: [PATCH 284/459] JS: Autoformat --- javascript/ql/src/semmle/javascript/AMD.qll | 3 +-- .../ql/src/semmle/javascript/frameworks/LazyCache.qll | 7 ++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll index 2beee7f6ce9..6d86b4d03a6 100644 --- a/javascript/ql/src/semmle/javascript/AMD.qll +++ b/javascript/ql/src/semmle/javascript/AMD.qll @@ -60,8 +60,7 @@ class AmdModuleDefinition extends CallExpr { result instanceof DataFlow::ValueNode } - private - DataFlow::Node getFactoryNodeInternal() { + private DataFlow::Node getFactoryNodeInternal() { result = DataFlow::valueNode(getLastArgument()) or result = getFactoryNodeInternal().getAPredecessor() } diff --git a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll index 0477c14acac..510d22dbddd 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll @@ -10,8 +10,7 @@ module LazyCache { * * A lazy-cache object, usually created through an expression of form `require('lazy-cache')(require)`. */ - deprecated - class LazyCacheObject extends DataFlow::SourceNode { + deprecated class LazyCacheObject extends DataFlow::SourceNode { LazyCacheObject() { // Use `require` directly instead of `moduleImport` to avoid recursion. // For the same reason, avoid `Import.getImportedPath`. @@ -55,9 +54,7 @@ module LazyCache { override PathExpr getImportedPath() { result = getArgument(0) } - private LazyCacheVariable getVariable() { - result = cache - } + private LazyCacheVariable getVariable() { result = cache } pragma[noopt] override DataFlow::Node getImportedModuleNode() { From b267df00770e17265df5aba16288744017965d93 Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Fri, 3 Apr 2020 00:02:14 +0100 Subject: [PATCH 285/459] Address review comments + make article intro consistent with map topic --- docs/language/learn-ql/introduction-to-ql.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index e154b95fb09..9deb7523661 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -1,7 +1,7 @@ Introduction to QL ================== -Work through some simple exercises to learn about the basics of QL and CodeQL. +Work through some simple exercises and examples to learn about the basics of QL and CodeQL. Basic syntax ------------ @@ -12,6 +12,9 @@ QL is a logic programming language, so it is built up of logical formulas. QL us QL also supports recursion and aggregates. This allows you to write complex recursive queries using simple QL syntax and directly use aggregates such as ``count``, ``sum``, and ``average``. +Running a query +--------------- + You can try out the following examples and exercises using `CodeQL for VS Code `__, or you can run them in the `query console on LGTM.com `__. Before you can run a query on LGTM.com, you need to select a language and project to query (for these logic examples, any language and project will do). Once you have selected a language, the query console is populated with the query: @@ -45,7 +48,7 @@ Note that ``int`` specifies that the **type** of ``x`` and ``y`` is 'integer'. T Simple exercises ---------------- -You can try to write simple queries using the some of the basic functions that are available for the ``int``, ``date``, ``float``, ``boolean`` and ``string`` types. To apply a function, append it to the argument. For example, ``1.toString()`` converts the value ``1`` to a string. Notice that as you start typing a function, a pop-up is displayed making it easy to select the function that you want. Also note that you can apply multiple functions in succession. For example, ``100.log().sqrt()`` first takes the natural logarithm of 100 and then computes the square root of the result. +You can write simple queries using the some of the basic functions that are available for the ``int``, ``date``, ``float``, ``boolean`` and ``string`` types. To apply a function, append it to the argument. For example, ``1.toString()`` converts the value ``1`` to a string. Notice that as you start typing a function, a pop-up is displayed making it easy to select the function that you want. Also note that you can apply multiple functions in succession. For example, ``100.log().sqrt()`` first takes the natural logarithm of 100 and then computes the square root of the result. Exercise 1 ~~~~~~~~~~ @@ -113,7 +116,8 @@ To simplify the query, we can introduce a class ``SmallInt`` representing the in Example CodeQL queries ---------------------- -The previous examples used the primitive types built in to QL. Although we chose a project to query, they did not use the project-specific database. The following example queries *do* use these databases and give you an idea of how CodeQL is used to analyze projects. +The previous examples used the primitive types built in to QL. Although we chose a project to query, we didn't use the information in that project's database. +The following example queries *do* use these databases and give you an idea of how to use CodeQL to analyze projects. Queries using the CodeQL libraries can find errors and uncover variants of important security vulnerabilities in codebases. Visit `GitHub Security Lab `__ to read about examples of vulnerabilities that we have recently found in open source projects. From e46cde17a1100e7c84308b0c892ad5a4ba3812f4 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 3 Apr 2020 09:42:05 +0200 Subject: [PATCH 286/459] add a "../" removing taint-step for js/path-injection --- .../security/dataflow/TaintedPath.qll | 8 ++ .../dataflow/TaintedPathCustomizations.qll | 54 +++++++- .../CWE-022/TaintedPath/TaintedPath.expected | 120 ++++++++++++++++++ .../CWE-022/TaintedPath/TaintedPath.js | 9 ++ 4 files changed, 190 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll index 06b0a6eb9e6..ab86f72631f 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll @@ -206,6 +206,14 @@ module TaintedPath { dstlabel.isNormalized() ) or + // foo.replace(/(\.\.\/)*/, "") and similar + exists(DotDotSlashPrefixRemovingReplace call | + src = call.getInput() and + dst = call.getOutput() and + dstlabel.isAbsolute() and // result can be absolute + dstlabel.toAbsolute() = srclabel.toAbsolute() // preserves normalization status + ) + or // path.join() exists(DataFlow::CallNode join, int n | join = NodeJSLib::Path::moduleMember("join").getACall() diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index c55fa8bad33..66708b4630e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -225,7 +225,8 @@ module TaintedPath { term.getAMatchedString() = "/" or term.getAMatchedString() = "." or term.getAMatchedString() = ".." - ) + ) and + not this instanceof DotDotSlashPrefixRemovingReplace } /** @@ -239,6 +240,57 @@ module TaintedPath { DataFlow::Node getOutput() { result = output } } + /** + * A call that removes all instances of "../" in the prefix of the string. + */ + class DotDotSlashPrefixRemovingReplace extends DataFlow::CallNode { + DataFlow::Node input; + DataFlow::Node output; + + DotDotSlashPrefixRemovingReplace() { + this.getCalleeName() = "replace" and + input = getReceiver() and + output = this and + exists(RegExpLiteral literal, RegExpTerm term | + getArgument(0).getALocalSource().asExpr() = literal and + (term instanceof RegExpStar or term instanceof RegExpPlus) and + term.getChild(0) = getADotDotSlashMatcher() + | + literal.getRoot() = term + or + exists(RegExpSequence seq | seq.getNumChild() = 2 and literal.getRoot() = seq | + seq.getChild(0) instanceof RegExpCaret and + seq.getChild(1) = term + ) + ) + } + + /** + * Gets the input path to be sanitized. + */ + DataFlow::Node getInput() { result = input } + + /** + * Gets the path where prefix "../" has been removed. + */ + DataFlow::Node getOutput() { result = output } + } + + /** + * Gets a RegExpTerm that matches a variation of "../". + */ + private RegExpTerm getADotDotSlashMatcher() { + result.getAMatchedString() = "../" + or + exists(RegExpSequence seq | seq = result | + seq.getChild(0).getConstantValue() = "." and + seq.getChild(1).getConstantValue() = "." and + seq.getAChild().getAMatchedString() = "/" + ) + or + exists(RegExpGroup group | result = group | group.getChild(0) = getADotDotSlashMatcher()) + } + /** * A call that removes all "." or ".." from a path, without also removing all forward slashes. */ diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index ec4531fde13..34dbe73a674 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1277,6 +1277,52 @@ nodes | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | | normalizedPaths.js:11:7:11:27 | path | | normalizedPaths.js:11:7:11:27 | path | | normalizedPaths.js:11:7:11:27 | path | @@ -4385,6 +4431,30 @@ edges | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path | | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path | | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | @@ -4561,6 +4631,54 @@ edges | TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path | | normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path | | normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path | @@ -6391,6 +6509,8 @@ edges | TaintedPath.js:184:29:184:53 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:184:29:184:53 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | | TaintedPath.js:185:29:185:51 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:185:29:185:51 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | | normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | | normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | | normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js index 0ecf680367f..506dc280a3d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js @@ -191,4 +191,13 @@ var server = http.createServer(function(req, res) { res.write(fs.readFileSync(path.replace(/\./g, ''))); // OK res.write(fs.readFileSync(path.replace(/\.\.|BLA/g, ''))); // OK } + + // removing of "../" from prefix. + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/^(\.\.[\/\\])+/, ''))); // OK + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.[\/\\])+/, ''))); // OK + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.\/)+/, ''))); // OK + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.\/)*/, ''))); // OK + + res.write(fs.readFileSync("prefix" + path.replace(/^(\.\.[\/\\])+/, ''))); // NOT OK - not normalized + res.write(fs.readFileSync(pathModule.normalize(path).replace(/^(\.\.[\/\\])+/, ''))); // NOT OK (can be absolute) }); \ No newline at end of file From 0f70944a5b02a28551e5c47a6cd210a49df2fcd7 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 3 Apr 2020 09:55:41 +0200 Subject: [PATCH 287/459] C++: Move ValueNumberPropertyProvider into its own file to prevent accidental imports --- .../aliased_ssa/gvn/PrintValueNumbering.qll | 17 +++++++++++++++++ .../aliased_ssa/gvn/ValueNumbering.qll | 15 --------------- 2 files changed, 17 insertions(+), 15 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ From 0b12c1519bbf3af3b555baa67b337746867ee0c1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 3 Apr 2020 10:06:37 +0200 Subject: [PATCH 288/459] C++/C#: Sync identical files --- .../raw/gvn/PrintValueNumbering.qll | 17 +++++++++++++++++ .../implementation/raw/gvn/ValueNumbering.qll | 15 --------------- .../unaliased_ssa/gvn/PrintValueNumbering.qll | 17 +++++++++++++++++ .../unaliased_ssa/gvn/ValueNumbering.qll | 15 --------------- .../raw/gvn/PrintValueNumbering.qll | 17 +++++++++++++++++ .../implementation/raw/gvn/ValueNumbering.qll | 15 --------------- .../unaliased_ssa/gvn/PrintValueNumbering.qll | 17 +++++++++++++++++ .../unaliased_ssa/gvn/ValueNumbering.qll | 15 --------------- 8 files changed, 68 insertions(+), 60 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll create mode 100644 cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll create mode 100644 csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ From 1e73528102298491a843f08589c6bac7ec5e5b28 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 3 Apr 2020 10:08:00 +0200 Subject: [PATCH 289/459] C++/C#: Add synchronization --- config/identical-files.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/identical-files.json b/config/identical-files.json index b16b61df654..a5af067ab5d 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -242,6 +242,13 @@ "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll", "csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll" ], + "C++ IR PrintValueNumbering": [ + "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll", + "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll", + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll" + ], "C++ IR ConstantAnalysis": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll", From 1bcf187c3ed13fb8a5aae1fd97acc67b00f694eb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 3 Apr 2020 09:17:33 +0100 Subject: [PATCH 290/459] C++: Rename Strings.qll -> StdString.qll. --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 2 +- .../cpp/models/implementations/{Strings.qll => StdString.qll} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename cpp/ql/src/semmle/code/cpp/models/implementations/{Strings.qll => StdString.qll} (100%) diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 3dd720b41ab..f02d05be711 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -12,5 +12,5 @@ private import implementations.Strcat private import implementations.Strcpy private import implementations.Strdup private import implementations.Strftime -private import implementations.Strings +private import implementations.StdString private import implementations.Swap diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll similarity index 100% rename from cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll rename to cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll From 73bfd819d92c02dbfb6f6871d3f0a3be6a6a5677 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 3 Apr 2020 09:23:31 +0100 Subject: [PATCH 291/459] C++: Rename classes. --- .../semmle/code/cpp/models/implementations/StdString.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 e9630050f74..80fe85e9f13 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -3,8 +3,8 @@ import semmle.code.cpp.models.interfaces.Taint /** * The `std::basic_string` constructor(s). */ -class StringConstructor extends TaintFunction { - StringConstructor() { this.hasQualifiedName("std", "basic_string", "basic_string") } +class StdStringConstructor extends TaintFunction { + StdStringConstructor() { this.hasQualifiedName("std", "basic_string", "basic_string") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any constructor argument to return value @@ -16,8 +16,8 @@ class StringConstructor extends TaintFunction { /** * The standard function `std::string.c_str`. */ -class StringCStr extends TaintFunction { - StringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") } +class StdStringCStr extends TaintFunction { + StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value From 08fbd1d2ad7d84adeded20f0885890d5243fe891 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 3 Apr 2020 10:25:46 +0200 Subject: [PATCH 292/459] C#: Update change notes --- change-notes/1.24/analysis-csharp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.24/analysis-csharp.md b/change-notes/1.24/analysis-csharp.md index 057f06685cf..a745e985eae 100644 --- a/change-notes/1.24/analysis-csharp.md +++ b/change-notes/1.24/analysis-csharp.md @@ -44,5 +44,6 @@ The following changes in version 1.24 affect C# analysis in all applications. * [Code contracts](https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts) are now recognized, and are treated like any other assertion methods. * Expression nullability flow state is given by the predicates `Expr.hasNotNullFlowState()` and `Expr.hasMaybeNullFlowState()`. * `stackalloc` array creations are now represented by the QL class `Stackalloc`. Previously they were represented by the class `ArrayCreation`. +* A new class `RemoteFlowSink` has been added to model sinks where data might be exposed to external users. Examples include web page output, e-mails, and cookies. ## Changes to autobuilder From 6a26a6542a2b51975e01558bd0ba7afb1e331057 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Fri, 3 Apr 2020 09:42:25 +0100 Subject: [PATCH 293/459] C#: Remove a function. --- csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs index d7b973dd350..9786e4dcca6 100644 --- a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs @@ -39,11 +39,11 @@ namespace Semmle.Autobuild { RootDirectory = actions.GetCurrentDirectory(); VsToolsVersion = actions.GetEnvironmentVariable(prefix + "VSTOOLS_VERSION"); - MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS").AsStringWithExpandedEnvVarsMaybeNull(actions); + MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS")?.AsStringWithExpandedEnvVars(actions); MsBuildPlatform = actions.GetEnvironmentVariable(prefix + "MSBUILD_PLATFORM"); MsBuildConfiguration = actions.GetEnvironmentVariable(prefix + "MSBUILD_CONFIGURATION"); MsBuildTarget = actions.GetEnvironmentVariable(prefix + "MSBUILD_TARGET"); - DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS").AsStringWithExpandedEnvVarsMaybeNull(actions); + DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS")?.AsStringWithExpandedEnvVars(actions); DotNetVersion = actions.GetEnvironmentVariable(prefix + "DOTNET_VERSION"); BuildCommand = actions.GetEnvironmentVariable(prefix + "BUILD_COMMAND"); Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsListWithExpandedEnvVars(actions, new string[0]); @@ -107,9 +107,6 @@ namespace Semmle.Autobuild static readonly Regex linuxEnvRegEx = new Regex(@"\$([a-zA-Z_][a-zA-Z_0-9]*)", RegexOptions.Compiled); - public static string? AsStringWithExpandedEnvVarsMaybeNull(this string? value, IBuildActions actions) => - value?.AsStringWithExpandedEnvVars(actions); - public static string AsStringWithExpandedEnvVars(this string value, IBuildActions actions) { if (string.IsNullOrEmpty(value)) From 94751c1b31cec3a3b1bccac9031e7ac9028f710c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 3 Apr 2020 11:08:31 +0200 Subject: [PATCH 294/459] dst can be relative for "../" replace call --- .../security/dataflow/TaintedPath.qll | 2 +- .../CWE-022/TaintedPath/TaintedPath.expected | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll index ab86f72631f..6ba6407e9e4 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll @@ -210,7 +210,7 @@ module TaintedPath { exists(DotDotSlashPrefixRemovingReplace call | src = call.getInput() and dst = call.getOutput() and - dstlabel.isAbsolute() and // result can be absolute + (srclabel.isNonNormalized() or dstlabel.isAbsolute()) and // if src is normalized, then dst must be absolute (if dst is relative, then dst is sanitized) dstlabel.toAbsolute() = srclabel.toAbsolute() // preserves normalization status ) or diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index 34dbe73a674..e8bbbd87f01 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1294,6 +1294,10 @@ nodes | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | @@ -4639,6 +4643,22 @@ edges | TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | From adde52d33cb1fa03ffb605f610ab221b83fcd85e Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Fri, 3 Apr 2020 10:36:47 +0100 Subject: [PATCH 295/459] C#: Add missing files --- csharp/extractor/Semmle.Util/FileRenamer.cs | 34 +++++++++++++++++++ .../Semmle.Util/TemporaryDirectory.cs | 30 ++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 csharp/extractor/Semmle.Util/FileRenamer.cs create mode 100644 csharp/extractor/Semmle.Util/TemporaryDirectory.cs diff --git a/csharp/extractor/Semmle.Util/FileRenamer.cs b/csharp/extractor/Semmle.Util/FileRenamer.cs new file mode 100644 index 00000000000..ad5001f7e13 --- /dev/null +++ b/csharp/extractor/Semmle.Util/FileRenamer.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Semmle.Util +{ + /// + /// Utility to temporarily rename a set of files. + /// + public sealed class FileRenamer : IDisposable + { + readonly string[] files; + const string suffix = ".codeqlhidden"; + + public FileRenamer(IEnumerable oldFiles) + { + files = oldFiles.Select(f => f.FullName).ToArray(); + + foreach (var file in files) + { + File.Move(file, file + suffix); + } + } + + public void Dispose() + { + foreach (var file in files) + { + File.Move(file + suffix, file); + } + } + } +} diff --git a/csharp/extractor/Semmle.Util/TemporaryDirectory.cs b/csharp/extractor/Semmle.Util/TemporaryDirectory.cs new file mode 100644 index 00000000000..a155372c9d8 --- /dev/null +++ b/csharp/extractor/Semmle.Util/TemporaryDirectory.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace Semmle.Util +{ + /// + /// A temporary directory that is created within the system temp directory. + /// When this object is disposed, the directory is deleted. + /// + public sealed class TemporaryDirectory : IDisposable + { + public DirectoryInfo DirInfo { get; } + + public TemporaryDirectory(string name) + { + DirInfo = new DirectoryInfo(name); + DirInfo.Create(); + } + + public void Dispose() + { + DirInfo.Delete(true); + } + + public override string ToString() => DirInfo.FullName.ToString(); + } +} From c54cddead16714e9ce5c9479ce7c4ace2c5f5f49 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 3 Apr 2020 12:42:06 +0200 Subject: [PATCH 296/459] C++: Include PrintValueNumbering in testcase --- .../library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql index 528bb6174a5..3debea869b4 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql @@ -5,3 +5,4 @@ import semmle.code.cpp.ir.PrintIR import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.ValueNumbering +import semmle.code.cpp.ir.implementation.aliased_ssa.gvn.PrintValueNumbering From 4e2d6c0250b530ef88e8c453ac3d26c2c1e7458b Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 3 Apr 2020 12:45:56 +0200 Subject: [PATCH 297/459] C#: Add missing QL doc --- .../src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll | 1 + .../src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll | 1 + 2 files changed, 2 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll index e4552d77cae..c45bd9e8b39 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll @@ -4,6 +4,7 @@ import csharp private import Remote private import semmle.code.csharp.frameworks.system.net.Mail +/** Provides sinks for emails. */ module Email { /** A data flow sink for sending email. */ abstract class Sink extends DataFlow::ExprNode, RemoteFlowSink { } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll index a507ef0663b..2363e24ffeb 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll @@ -172,6 +172,7 @@ class WebPageWriteLiteralToSink extends HtmlSink { } } +/** An ASP.NET Core HTML sink. */ abstract class AspNetCoreHtmlSink extends HtmlSink { } /** From 9c2053168b283e8505ed150683315e95c7574ad6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 3 Apr 2020 15:46:47 +0200 Subject: [PATCH 298/459] writing out the truth table for DotDotSlashPrefixRemovingReplace --- .../security/dataflow/TaintedPath.qll | 12 +++-- .../CWE-022/TaintedPath/TaintedPath.expected | 48 +++++-------------- 2 files changed, 21 insertions(+), 39 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll index 6ba6407e9e4..3a8a20895d8 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll @@ -209,9 +209,15 @@ module TaintedPath { // foo.replace(/(\.\.\/)*/, "") and similar exists(DotDotSlashPrefixRemovingReplace call | src = call.getInput() and - dst = call.getOutput() and - (srclabel.isNonNormalized() or dstlabel.isAbsolute()) and // if src is normalized, then dst must be absolute (if dst is relative, then dst is sanitized) - dstlabel.toAbsolute() = srclabel.toAbsolute() // preserves normalization status + dst = call.getOutput() + | + // the 4 possible combinations of normalized + relative for `srclabel`, and the possible values for `dstlabel` in each case. + srclabel.isNonNormalized() and srclabel.isRelative() // raw + relative -> any() + or + srclabel.isNormalized() and srclabel.isAbsolute() and srclabel = dstlabel // normalized + absolute -> normalized + absolute + or + srclabel.isNonNormalized() and srclabel.isAbsolute() and dstlabel.isAbsolute() // raw + absolute -> raw/normalized + absolute + // normalized + relative -> none() ) or // path.join() diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index e8bbbd87f01..fb4fcb3503e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1298,10 +1298,10 @@ nodes | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | @@ -1319,14 +1319,6 @@ nodes | TaintedPath.js:202:50:202:53 | path | | TaintedPath.js:202:50:202:53 | path | | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:202:50:202:53 | path | | normalizedPaths.js:11:7:11:27 | path | | normalizedPaths.js:11:7:11:27 | path | | normalizedPaths.js:11:7:11:27 | path | @@ -4451,14 +4443,6 @@ edges | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | -| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | @@ -4667,6 +4651,14 @@ edges | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | @@ -4675,22 +4667,6 @@ edges | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | -| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | From 3653627650d9a84822d49f1ba8c6b260dd20552e Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 2 Apr 2020 09:46:59 +0200 Subject: [PATCH 299/459] C++: Let configuration class extend singleton --- .../code/cpp/ir/dataflow/DefaultTaintTracking.qll | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index c0f763a78bc..a20bbf0daf6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -394,15 +394,21 @@ Function resolveCall(Call call) { * taint paths. */ module TaintedWithPath { + private newtype TSingleton = MkSingleton() + /** * A taint-tracking configuration that matches sources and sinks in the same * way as the `tainted` predicate. + * + * Override `isSink` and `taintThroughGlobals` as needed, but do not provide + * a characteristic predicate. */ - class TaintTrackingConfiguration extends int { - TaintTrackingConfiguration() { this = 1 } - + class TaintTrackingConfiguration extends TSingleton { /** Override this to specify which elements are sinks in this configuration. */ abstract predicate isSink(Element e); + + /** Gets a textual representation of this element. */ + string toString() { result = "TaintTrackingConfiguration" } } private class AdjustedConfiguration extends DataFlow3::Configuration { From 427815d3d14adf7e3cc07b9715ee9085b7e544d3 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 2 Apr 2020 08:33:23 +0200 Subject: [PATCH 300/459] C++: taintedWithPath QLDoc + simplification --- .../code/cpp/ir/dataflow/DefaultTaintTracking.qll | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index a20bbf0daf6..e0f2d3ea99a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -511,10 +511,19 @@ module TaintedWithPath { key = "semmle.label" and val = n.toString() } + /** + * Holds if `tainted` may contain taint from `source`, where `sourceNode` and + * `sinkNode` are the corresponding `PathNode`s that can be used in a query + * to provide path explanations. Extend `TaintTrackingConfiguration` to use + * this predicate. + * + * A tainted expression is either directly user input, or is computed from + * user input in a way that users can probably control the exact output of + * the computation. + */ predicate taintedWithPath(Expr source, Element tainted, PathNode sourceNode, PathNode sinkNode) { - exists(AdjustedConfiguration cfg, DataFlow3::PathNode sinkInner, DataFlow::Node sink | + exists(AdjustedConfiguration cfg, DataFlow3::PathNode sinkInner | sourceNode.(WrapPathNode).inner().getNode() = getNodeForSource(source) and - sinkInner.getNode() = sink and cfg.hasFlowPath(sourceNode.(WrapPathNode).inner(), sinkInner) and tainted = adjustedSink(sinkInner.getNode()) and tainted = sinkNode.(FinalPathNode).inner() From e916f07a8e3b55e95976dcf46c5a98004ec4c3c9 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 2 Apr 2020 09:43:37 +0200 Subject: [PATCH 301/459] C++: Formatting fixups --- .../src/Security/CWE/CWE-134/UncontrolledFormatString.ql | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql index 03d8e4bfb45..91ccc5c4d40 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql @@ -18,14 +18,15 @@ import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.TaintTracking import TaintedWithPath -class TaintedPathConfiguration extends TaintTrackingConfiguration { +class Configuration extends TaintTrackingConfiguration { override predicate isSink(Element tainted) { exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _)) } } -from PrintfLikeFunction printf, Expr arg, PathNode sourceNode, - PathNode sinkNode, string printfFunction, Expr userValue, string cause +from + PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode, + string printfFunction, Expr userValue, string cause where printf.outermostWrapperFunctionCall(arg, printfFunction) and taintedWithPath(userValue, arg, sourceNode, sinkNode) and From 36da2d1dae244c70190534aa01068aab9d86925d Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 2 Apr 2020 13:29:19 +0200 Subject: [PATCH 302/459] C++: Manipulate the source end of paths too Without this, we get duplicate alerts in some cases and unnatural-looking source nodes in other cases. The source nodes were often `Conversion`s. --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 61 +++++++--- .../CWE-022/semmle/tests/TaintedPath.expected | 4 +- .../CWE-134/semmle/argv/argvLocal.expected | 109 ++++++++++++------ .../CWE-134/semmle/funcs/funcsLocal.expected | 37 ++++-- .../UncontrolledFormatString.expected | 7 -- .../CWE/CWE-134/semmle/ifs/ifs.expected | 50 +++++++- .../TaintedAllocationSize.expected | 37 ++++-- 7 files changed, 224 insertions(+), 81 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index e0f2d3ea99a..498449bdd71 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -440,13 +440,23 @@ module TaintedWithPath { * coming from the data-flow library with a node that matches exactly the * `Element` sink that's requested. * - * The same should ideally be done with the source, but we haven't seen a - * need for it yet. + * The same is done for sources. */ private newtype TPathNode = TWrapPathNode(DataFlow3::PathNode n) or - TFinalPathNode(Element e) { exists(TaintTrackingConfiguration cfg | cfg.isSink(e)) } + // There's a single newtype constructor for both sources and sinks since + // that makes it easiest to deal with the case where source = sink. + TEndpointPathNode(Element e) { + exists(AdjustedConfiguration cfg, DataFlow3::Node sourceNode, DataFlow3::Node sinkNode | + cfg.hasFlow(sourceNode, sinkNode) + | + sourceNode = getNodeForSource(e) + or + e = adjustedSink(sinkNode) and + exists(TaintTrackingConfiguration ttCfg | ttCfg.isSink(e)) + ) + } /** An opaque type used for the nodes of a data-flow path. */ class PathNode extends TPathNode { @@ -479,8 +489,8 @@ module TaintedWithPath { } } - private class FinalPathNode extends PathNode, TFinalPathNode { - Element inner() { this = TFinalPathNode(result) } + private class EndpointPathNode extends PathNode, TEndpointPathNode { + Expr inner() { this = TEndpointPathNode(result) } override string toString() { result = this.inner().toString() } @@ -494,15 +504,39 @@ module TaintedWithPath { } } + /** A PathNode whose `Element` is a source. It may also be a sink. */ + private class InitialPathNode extends EndpointPathNode { + InitialPathNode() { exists(getNodeForSource(this.inner())) } + } + + /** A PathNode whose `Element` is a sink. It may also be a source. */ + private class FinalPathNode extends EndpointPathNode { + FinalPathNode() { exists(TaintTrackingConfiguration cfg | cfg.isSink(this.inner())) } + } + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ query predicate edges(PathNode a, PathNode b) { DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), b.(WrapPathNode).inner()) or - // To avoid showing trivial-looking steps, we replace the last node instead + // To avoid showing trivial-looking steps, we _replace_ the last node instead // of adding an edge out of it. - exists(WrapPathNode replaced | - DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), replaced.inner()) and - b.(FinalPathNode).inner() = adjustedSink(replaced.inner().getNode()) + exists(WrapPathNode sinkNode | + DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), sinkNode.inner()) and + b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode()) + ) + or + // Same for the first node + exists(WrapPathNode sourceNode | + DataFlow3::PathGraph::edges(sourceNode.inner(), b.(WrapPathNode).inner()) and + sourceNode.inner().getNode() = getNodeForSource(a.(InitialPathNode).inner()) + ) + or + // Finally, handle the case where the path goes directly from a source to a + // sink, meaning that they both need to be translated. + exists(WrapPathNode sinkNode, WrapPathNode sourceNode | + DataFlow3::PathGraph::edges(sourceNode.inner(), sinkNode.inner()) and + sourceNode.inner().getNode() = getNodeForSource(a.(InitialPathNode).inner()) and + b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode()) ) } @@ -522,10 +556,11 @@ module TaintedWithPath { * the computation. */ predicate taintedWithPath(Expr source, Element tainted, PathNode sourceNode, PathNode sinkNode) { - exists(AdjustedConfiguration cfg, DataFlow3::PathNode sinkInner | - sourceNode.(WrapPathNode).inner().getNode() = getNodeForSource(source) and - cfg.hasFlowPath(sourceNode.(WrapPathNode).inner(), sinkInner) and - tainted = adjustedSink(sinkInner.getNode()) and + exists(AdjustedConfiguration cfg, DataFlow3::Node flowSource, DataFlow3::Node flowSink | + source = sourceNode.(InitialPathNode).inner() and + flowSource = getNodeForSource(source) and + cfg.hasFlow(flowSource, flowSink) and + tainted = adjustedSink(flowSink) and tainted = sinkNode.(FinalPathNode).inner() ) } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected index e84389872fd..d7db531fbde 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected @@ -1,11 +1,13 @@ edges | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | (const char *)... | +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | (const char *)... | +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | nodes | test.c:9:23:9:26 | argv | semmle.label | argv | +| test.c:9:23:9:26 | argv | semmle.label | argv | | test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | | test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | | test.c:17:11:17:18 | fileName | semmle.label | fileName | -| test.c:27:11:27:18 | fileName | semmle.label | fileName | #select | test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename) | test.c:9:23:9:26 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index b33bdb63e94..181414f12d0 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -1,102 +1,136 @@ edges | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | (const char *)... | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | (const char *)... | | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | (const char *)... | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | (const char *)... | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | (const char *)... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | (const char *)... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | (const char *)... | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | (const char *)... | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | | argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | (const char *)... | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | (const char *)... | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | | argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | | argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | | argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | | argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | (const char *)... | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | (const char *)... | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | | argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | | argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | | argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (const char *)... | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (const char *)... | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | (char *)... | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | (char *)... | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | nodes -| argvLocal.c:15:9:15:17 | Correct | semmle.label | Correct | -| argvLocal.c:16:15:16:23 | Correct | semmle.label | Correct | -| argvLocal.c:20:9:20:10 | c1 | semmle.label | c1 | -| argvLocal.c:21:15:21:16 | c1 | semmle.label | c1 | -| argvLocal.c:25:9:25:10 | c2 | semmle.label | c2 | -| argvLocal.c:26:15:26:16 | c2 | semmle.label | c2 | -| argvLocal.c:30:9:30:11 | * ... | semmle.label | * ... | -| argvLocal.c:31:15:31:17 | * ... | semmle.label | * ... | -| argvLocal.c:36:9:36:10 | c4 | semmle.label | c4 | -| argvLocal.c:37:15:37:16 | c4 | semmle.label | c4 | -| argvLocal.c:41:9:41:10 | c5 | semmle.label | c5 | -| argvLocal.c:42:15:42:16 | c5 | semmle.label | c5 | -| argvLocal.c:47:9:47:10 | c6 | semmle.label | c6 | -| argvLocal.c:48:15:48:16 | c6 | semmle.label | c6 | -| argvLocal.c:51:9:51:21 | ... + ... | semmle.label | ... + ... | -| argvLocal.c:52:15:52:27 | ... + ... | semmle.label | ... + ... | -| argvLocal.c:55:9:55:12 | ... ++ | semmle.label | ... ++ | -| argvLocal.c:56:15:56:18 | -- ... | semmle.label | -- ... | -| argvLocal.c:59:9:59:20 | ... ? ... : ... | semmle.label | ... ? ... : ... | -| argvLocal.c:60:15:60:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | -| argvLocal.c:63:9:63:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | -| argvLocal.c:64:15:64:32 | ... ? ... : ... | semmle.label | ... ? ... : ... | -| argvLocal.c:68:9:68:10 | c7 | semmle.label | c7 | -| argvLocal.c:69:15:69:16 | c7 | semmle.label | c7 | -| argvLocal.c:74:9:74:10 | c8 | semmle.label | c8 | -| argvLocal.c:75:15:75:16 | c8 | semmle.label | c8 | -| argvLocal.c:80:9:80:10 | c9 | semmle.label | c9 | -| argvLocal.c:81:15:81:16 | c9 | semmle.label | c9 | -| argvLocal.c:86:9:86:11 | c91 | semmle.label | c91 | -| argvLocal.c:87:15:87:17 | c91 | semmle.label | c91 | -| argvLocal.c:91:18:91:20 | c10 | semmle.label | c10 | -| argvLocal.c:92:24:92:26 | c10 | semmle.label | c10 | +| argvLocal.c:95:9:95:12 | argv | semmle.label | argv | | argvLocal.c:95:9:95:12 | argv | semmle.label | argv | | argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | @@ -104,10 +138,12 @@ nodes | argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | | argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | | argvLocal.c:96:15:96:18 | argv | semmle.label | argv | +| argvLocal.c:96:15:96:18 | argv | semmle.label | argv | | argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | | argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | | argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | | argvLocal.c:100:7:100:10 | argv | semmle.label | argv | +| argvLocal.c:100:7:100:10 | argv | semmle.label | argv | | argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | @@ -117,6 +153,7 @@ nodes | argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | | argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | | argvLocal.c:105:14:105:17 | argv | semmle.label | argv | +| argvLocal.c:105:14:105:17 | argv | semmle.label | argv | | argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | @@ -134,6 +171,7 @@ nodes | argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | | argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | | argvLocal.c:115:13:115:16 | argv | semmle.label | argv | +| argvLocal.c:115:13:115:16 | argv | semmle.label | argv | | argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | @@ -147,6 +185,7 @@ nodes | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | | argvLocal.c:126:10:126:13 | argv | semmle.label | argv | +| argvLocal.c:126:10:126:13 | argv | semmle.label | argv | | argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | @@ -165,8 +204,6 @@ nodes | argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | | argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | | argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | -| argvLocal.c:139:9:139:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | -| argvLocal.c:140:15:140:32 | ... ? ... : ... | semmle.label | ... ? ... : ... | | argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | @@ -176,6 +213,7 @@ nodes | argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | | argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | | argvLocal.c:149:11:149:14 | argv | semmle.label | argv | +| argvLocal.c:149:11:149:14 | argv | semmle.label | argv | | argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | @@ -185,6 +223,7 @@ nodes | argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | | argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | | argvLocal.c:156:23:156:26 | argv | semmle.label | argv | +| argvLocal.c:156:23:156:26 | argv | semmle.label | argv | | argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:157:9:157:10 | i9 | semmle.label | i9 | @@ -192,6 +231,7 @@ nodes | argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | | argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | | argvLocal.c:163:22:163:25 | argv | semmle.label | argv | +| argvLocal.c:163:22:163:25 | argv | semmle.label | argv | | argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:164:9:164:11 | i91 | semmle.label | i91 | @@ -199,6 +239,7 @@ nodes | argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | | argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | | argvLocal.c:168:18:168:21 | argv | semmle.label | argv | +| argvLocal.c:168:18:168:21 | argv | semmle.label | argv | | argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | | argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | | argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 889552641ef..556c2fca192 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -1,56 +1,75 @@ edges | funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | (const char *)... | | funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | | funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | (const char *)... | | funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | (const char *)... | +| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | (const char *)... | | funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | (const char *)... | | funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | (const char *)... | +| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | (const char *)... | | funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | nodes | funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | semmle.label | BufferMayWriteSideEffect | +| funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 | | funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 | -| funcsLocal.c:22:9:22:12 | %s | semmle.label | %s | | funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 | | funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 | | funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | +| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | | funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:31:19:31:21 | i41 | semmle.label | i41 | | funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 | | funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 | | funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | +| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | | funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:41:18:41:20 | i61 | semmle.label | i61 | | funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | | funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | | funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | -| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | -| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | -| funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 | #select -| funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | -| funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:26:8:26:9 | i3 | fgets | +| funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | +| funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:26:8:26:9 | i3 | fgets | | funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets | -| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:19:31:21 | i41 | fgets | -| funcsLocal.c:37:9:37:10 | i5 | funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | +| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:19:31:21 | i41 | fgets | +| funcsLocal.c:37:9:37:10 | i5 | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | | funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets | -| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets | +| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected index 09f550d1bd4..58e3dda0964 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected @@ -1,10 +1,3 @@ edges nodes -| globalVars.c:27:9:27:12 | copy | semmle.label | copy | -| globalVars.c:30:15:30:18 | copy | semmle.label | copy | -| globalVars.c:33:9:33:12 | %s | semmle.label | %s | -| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | -| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | -| globalVars.c:44:9:44:12 | %s | semmle.label | %s | -| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | #select diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected index 4a96784b3a4..62c36d0192d 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected @@ -1,44 +1,72 @@ edges | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | (const char *)... | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | (const char *)... | | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | (const char *)... | | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | (const char *)... | | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | (const char *)... | | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | (const char *)... | | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | (const char *)... | | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | (const char *)... | | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | (const char *)... | | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | (const char *)... | | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | (const char *)... | | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | (const char *)... | | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | (const char *)... | | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | (const char *)... | | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | (const char *)... | | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | (const char *)... | | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | (const char *)... | | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | (const char *)... | | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | (const char *)... | | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | (const char *)... | | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | (const char *)... | | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | (const char *)... | | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | nodes -| ifs.c:26:9:26:10 | c1 | semmle.label | c1 | -| ifs.c:32:9:32:10 | c2 | semmle.label | c2 | -| ifs.c:38:9:38:10 | c3 | semmle.label | c3 | -| ifs.c:44:9:44:10 | c4 | semmle.label | c4 | -| ifs.c:50:9:50:10 | c5 | semmle.label | c5 | -| ifs.c:56:9:56:10 | c6 | semmle.label | c6 | +| ifs.c:61:8:61:11 | argv | semmle.label | argv | | ifs.c:61:8:61:11 | argv | semmle.label | argv | | ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | @@ -46,60 +74,70 @@ nodes | ifs.c:62:9:62:10 | c7 | semmle.label | c7 | | ifs.c:62:9:62:10 | c7 | semmle.label | c7 | | ifs.c:68:8:68:11 | argv | semmle.label | argv | +| ifs.c:68:8:68:11 | argv | semmle.label | argv | | ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:74:8:74:11 | argv | semmle.label | argv | +| ifs.c:74:8:74:11 | argv | semmle.label | argv | | ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:75:9:75:10 | i1 | semmle.label | i1 | | ifs.c:75:9:75:10 | i1 | semmle.label | i1 | | ifs.c:75:9:75:10 | i1 | semmle.label | i1 | | ifs.c:80:8:80:11 | argv | semmle.label | argv | +| ifs.c:80:8:80:11 | argv | semmle.label | argv | | ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:86:8:86:11 | argv | semmle.label | argv | +| ifs.c:86:8:86:11 | argv | semmle.label | argv | | ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:87:9:87:10 | i3 | semmle.label | i3 | | ifs.c:87:9:87:10 | i3 | semmle.label | i3 | | ifs.c:87:9:87:10 | i3 | semmle.label | i3 | | ifs.c:92:8:92:11 | argv | semmle.label | argv | +| ifs.c:92:8:92:11 | argv | semmle.label | argv | | ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:98:8:98:11 | argv | semmle.label | argv | +| ifs.c:98:8:98:11 | argv | semmle.label | argv | | ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:99:9:99:10 | i5 | semmle.label | i5 | | ifs.c:99:9:99:10 | i5 | semmle.label | i5 | | ifs.c:99:9:99:10 | i5 | semmle.label | i5 | | ifs.c:105:8:105:11 | argv | semmle.label | argv | +| ifs.c:105:8:105:11 | argv | semmle.label | argv | | ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:111:8:111:11 | argv | semmle.label | argv | +| ifs.c:111:8:111:11 | argv | semmle.label | argv | | ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:112:9:112:10 | i7 | semmle.label | i7 | | ifs.c:112:9:112:10 | i7 | semmle.label | i7 | | ifs.c:112:9:112:10 | i7 | semmle.label | i7 | | ifs.c:117:8:117:11 | argv | semmle.label | argv | +| ifs.c:117:8:117:11 | argv | semmle.label | argv | | ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:123:8:123:11 | argv | semmle.label | argv | +| ifs.c:123:8:123:11 | argv | semmle.label | argv | | ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:124:9:124:10 | i9 | semmle.label | i9 | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index d8b49226138..ddb16699fce 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -1,30 +1,53 @@ edges | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | (unsigned long)... | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | (unsigned long)... | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | (unsigned long)... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | (unsigned long)... | | test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | +| test.cpp:123:25:123:30 | call to getenv | test.cpp:127:24:127:27 | (size_t)... | +| test.cpp:123:25:123:30 | call to getenv | test.cpp:127:24:127:27 | size | +| test.cpp:123:25:123:30 | call to getenv | test.cpp:127:24:127:27 | size | | test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | (size_t)... | | test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | size | | test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | size | nodes | test.cpp:39:21:39:24 | argv | semmle.label | argv | -| test.cpp:41:38:41:53 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | +| test.cpp:39:21:39:24 | argv | semmle.label | argv | | test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | | test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | | test.cpp:42:38:42:44 | tainted | semmle.label | tainted | @@ -38,10 +61,6 @@ nodes | test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | | test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | | test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | -| test.cpp:43:48:43:63 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | -| test.cpp:44:38:44:47 | call to getTainted | semmle.label | call to getTainted | -| test.cpp:44:38:44:68 | ... * ... | semmle.label | ... * ... | -| test.cpp:44:53:44:68 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | | test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | | test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | | test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | @@ -53,7 +72,6 @@ nodes | test.cpp:49:26:49:29 | size | semmle.label | size | | test.cpp:49:26:49:29 | size | semmle.label | size | | test.cpp:49:26:49:29 | size | semmle.label | size | -| test.cpp:52:35:52:50 | sizeof(MyStruct) | semmle.label | sizeof(MyStruct) | | test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | | test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | | test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | @@ -62,11 +80,8 @@ nodes | test.cpp:52:54:52:60 | tainted | semmle.label | tainted | | test.cpp:52:54:52:60 | tainted | semmle.label | tainted | | test.cpp:52:54:52:60 | tainted | semmle.label | tainted | -| test.cpp:55:20:55:23 | size | semmle.label | size | -| test.cpp:68:18:68:21 | size | semmle.label | size | -| test.cpp:79:18:79:28 | ... - ... | semmle.label | ... - ... | +| test.cpp:123:25:123:30 | call to getenv | semmle.label | call to getenv | | test.cpp:123:25:123:38 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:126:24:126:35 | bounded_size | semmle.label | bounded_size | | test.cpp:127:24:127:27 | (size_t)... | semmle.label | (size_t)... | | test.cpp:127:24:127:27 | (size_t)... | semmle.label | (size_t)... | | test.cpp:127:24:127:27 | size | semmle.label | size | @@ -81,4 +96,4 @@ nodes | test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:52:35:52:60 | ... * ... | test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:25:123:38 | (const char *)... | test.cpp:127:24:127:27 | size | This allocation size is derived from $@ and might overflow | test.cpp:123:25:123:30 | call to getenv | user input (getenv) | +| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:25:123:30 | call to getenv | test.cpp:127:24:127:27 | size | This allocation size is derived from $@ and might overflow | test.cpp:123:25:123:30 | call to getenv | user input (getenv) | From 469bdae9b27ef296d0bceb8e37101bc4ed86b19d Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 3 Apr 2020 10:29:37 +0200 Subject: [PATCH 303/459] C++: More helpful toString for def. by ref. node --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 8 +++++ .../CWE-134/semmle/funcs/funcsLocal.expected | 30 +++++++++---------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 0ecb4ac596a..3f1ea39de09 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -239,6 +239,14 @@ class DefinitionByReferenceNode extends InstructionNode { Parameter getParameter() { exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex())) } + + override string toString() { + // This string should be unique enough to be helpful but common enough to + // avoid storing too many different strings. + result = + instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget().getName() + + " output argument" + } } /** diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 556c2fca192..c4dc83315e4 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -1,10 +1,10 @@ edges -| funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | (const char *)... | -| funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 | | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | (const char *)... | | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | -| funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | (const char *)... | -| funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | (const char *)... | +| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 | | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | (const char *)... | | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | @@ -13,12 +13,12 @@ edges | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | (const char *)... | -| funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | (const char *)... | | funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | (const char *)... | -| funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | (const char *)... | +| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 | | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | (const char *)... | | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | @@ -27,38 +27,38 @@ edges | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | -| funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | (const char *)... | -| funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | (const char *)... | | funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | nodes -| funcsLocal.c:16:8:16:9 | BufferMayWriteSideEffect | semmle.label | BufferMayWriteSideEffect | +| funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument | | funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 | | funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 | -| funcsLocal.c:26:8:26:9 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:26:8:26:9 | fgets output argument | semmle.label | fgets output argument | | funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 | | funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 | | funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | | funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | -| funcsLocal.c:31:19:31:21 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:31:19:31:21 | fgets output argument | semmle.label | fgets output argument | | funcsLocal.c:31:19:31:21 | i41 | semmle.label | i41 | | funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | -| funcsLocal.c:36:7:36:8 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:36:7:36:8 | gets output argument | semmle.label | gets output argument | | funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 | | funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 | | funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | | funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | -| funcsLocal.c:41:18:41:20 | BufferMustWriteSideEffect | semmle.label | BufferMustWriteSideEffect | +| funcsLocal.c:41:18:41:20 | gets output argument | semmle.label | gets output argument | | funcsLocal.c:41:18:41:20 | i61 | semmle.label | i61 | | funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | From aaebe3687e0d0ccf6c3eeeba99f96105e3fa5fcc Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 2 Apr 2020 16:04:14 +0200 Subject: [PATCH 304/459] C++: Fix copy-paste error in convertedExprNode --- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 3f1ea39de09..642180d0c2c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -297,7 +297,7 @@ ExprNode exprNode(Expr e) { result.getExpr() = e } * Gets the `Node` corresponding to `e`, if any. Here, `e` may be a * `Conversion`. */ -ExprNode convertedExprNode(Expr e) { result.getExpr() = e } +ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e } /** * Gets the `Node` corresponding to the value of `p` at function entry. From 3ec1f691c2b64aea0989f7926659943f05660489 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 2 Apr 2020 09:45:50 +0200 Subject: [PATCH 305/459] C++: First query with flow-paths through globals --- ...ncontrolledFormatStringThroughGlobalVar.ql | 23 ++++-- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 34 +++++++++ ...olledFormatStringThroughGlobalVar.expected | 70 +++++++++++++++++-- 3 files changed, 115 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql index f3cb4fcf1bb..88341f7ca9d 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql @@ -3,7 +3,7 @@ * @description Using externally-controlled format strings in * printf-style functions can lead to buffer overflows * or data representation problems. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/tainted-format-string-through-global @@ -16,15 +16,24 @@ import cpp import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath + +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _)) + } + + override predicate taintThroughGlobals() { any() } +} from - PrintfLikeFunction printf, Expr arg, string printfFunction, Expr userValue, string cause, - string globalVar + PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode, + string printfFunction, Expr userValue, string cause where printf.outermostWrapperFunctionCall(arg, printfFunction) and - not tainted(_, arg) and - taintedIncludingGlobalVars(userValue, arg, globalVar) and + not taintedWithoutGlobals(arg) and + taintedWithPath(userValue, arg, sourceNode, sinkNode) and isUserInput(userValue, cause) select arg, - "This value may flow through $@, originating from $@, and is a formatting argument to " + - printfFunction + ".", globalVarFromId(globalVar), globalVar, userValue, cause + "The value of this argument may come from $@ and is being used as a formatting argument to " + + printfFunction, userValue, cause diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 498449bdd71..c291246a774 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -407,6 +407,12 @@ module TaintedWithPath { /** Override this to specify which elements are sinks in this configuration. */ abstract predicate isSink(Element e); + /** + * Override this predicate to `any()` to allow taint to flow through global + * variables. + */ + predicate taintThroughGlobals() { none() } + /** Gets a textual representation of this element. */ string toString() { result = "TaintTrackingConfiguration" } } @@ -422,6 +428,12 @@ module TaintedWithPath { override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { instructionTaintStep(n1.asInstruction(), n2.asInstruction()) + or + exists(TaintTrackingConfiguration cfg | cfg.taintThroughGlobals() | + writesVariable(n1.asInstruction(), n2.asVariable().(GlobalOrNamespaceVariable)) + or + readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable)) + ) } override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) } @@ -564,4 +576,26 @@ module TaintedWithPath { tainted = sinkNode.(FinalPathNode).inner() ) } + + private predicate isGlobalVariablePathNode(WrapPathNode n) { + n.inner().getNode().asVariable() instanceof GlobalOrNamespaceVariable + } + + private predicate edgesWithoutGlobals(PathNode a, PathNode b) { + edges(a, b) and + not isGlobalVariablePathNode(a) and + not isGlobalVariablePathNode(b) + } + + /** + * Holds if `tainted` can be reached from a taint source without passing + * through a global variable. + */ + predicate taintedWithoutGlobals(Element tainted) { + exists(PathNode sourceNode, FinalPathNode sinkNode | + sourceNode.(WrapPathNode).inner().getNode() = getNodeForSource(_) and + edgesWithoutGlobals+(sourceNode, sinkNode) and + tainted = sinkNode.inner() + ) + } } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index 0f29313da8e..263399b2af8 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -1,5 +1,65 @@ -| globalVars.c:27:9:27:12 | copy | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:8:7:8:10 | copy | copy | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:30:15:30:18 | copy | This value may flow through $@, originating from $@, and is a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:8:7:8:10 | copy | copy | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:38:9:38:13 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:41:15:41:19 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:50:9:50:13 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv | +edges +| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | +| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | Store | +| globalVars.c:12:2:12:15 | Store | globalVars.c:8:7:8:10 | copy | +| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | Store | +| globalVars.c:16:2:16:12 | Store | globalVars.c:9:7:9:11 | copy2 | +| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | +| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | +| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | (const char *)... | +| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val | +| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | (const char *)... | +| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | +| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 | +nodes +| globalVars.c:8:7:8:10 | copy | semmle.label | copy | +| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 | +| globalVars.c:11:22:11:25 | argv | semmle.label | argv | +| globalVars.c:12:2:12:15 | Store | semmle.label | Store | +| globalVars.c:15:21:15:23 | val | semmle.label | val | +| globalVars.c:16:2:16:12 | Store | semmle.label | Store | +| globalVars.c:24:11:24:14 | argv | semmle.label | argv | +| globalVars.c:24:11:24:14 | argv | semmle.label | argv | +| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:27:9:27:12 | copy | semmle.label | copy | +| globalVars.c:27:9:27:12 | copy | semmle.label | copy | +| globalVars.c:27:9:27:12 | copy | semmle.label | copy | +| globalVars.c:30:15:30:18 | copy | semmle.label | copy | +| globalVars.c:30:15:30:18 | copy | semmle.label | copy | +| globalVars.c:30:15:30:18 | copy | semmle.label | copy | +| globalVars.c:35:11:35:14 | copy | semmle.label | copy | +| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | +| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | +| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | +| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | +| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | +| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | +| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | +| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | +| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | +#select +| globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | From 5822cd7b84471502e5e2551237aeebb1cb0e3d12 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 3 Apr 2020 08:35:42 +0200 Subject: [PATCH 306/459] C++: Put paths in the remaining LGTM-suite queries --- cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql | 18 ++++-- cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql | 17 ++++-- .../CWE-114/UncontrolledProcessOperation.ql | 25 +++++--- .../Security/CWE/CWE-120/UnboundedWrite.ql | 55 ++++++++++++------ .../CWE/CWE-290/AuthenticationBypass.ql | 24 +++++--- .../CWE/CWE-311/CleartextBufferWrite.ql | 16 +++-- .../Security/CWE/CWE-807/TaintedCondition.ql | 31 ++++++---- .../CWE/CWE-079/semmle/CgiXss/CgiXss.expected | 32 +++++++++- .../UncontrolledProcessOperation.expected | 27 ++++++++- .../semmle/tests/UnboundedWrite.expected | 3 + .../semmle/tests/UnboundedWrite.expected | 58 +++++++++++++++++-- .../AuthenticationBypass.expected | 36 +++++++++++- .../tests/CleartextBufferWrite.expected | 14 ++++- .../TaintedCondition.expected | 39 ++++++++++++- 14 files changed, 319 insertions(+), 76 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql index 8b7fb83df81..0e0c4add7f6 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql @@ -2,7 +2,7 @@ * @name CGI script vulnerable to cross-site scripting * @description Writing user input directly to a web page * allows for a cross-site scripting vulnerability. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cpp/cgi-xss @@ -13,6 +13,7 @@ import cpp import semmle.code.cpp.commons.Environment import semmle.code.cpp.security.TaintTracking +import TaintedWithPath /** A call that prints its arguments to `stdout`. */ class PrintStdoutCall extends FunctionCall { @@ -27,8 +28,13 @@ class QueryString extends EnvironmentRead { QueryString() { getEnvironmentVariable() = "QUERY_STRING" } } -from QueryString query, PrintStdoutCall call, Element printedArg -where - call.getAnArgument() = printedArg and - tainted(query, printedArg) -select printedArg, "Cross-site scripting vulnerability due to $@.", query, "this query data" +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(PrintStdoutCall call | call.getAnArgument() = tainted) + } +} + +from QueryString query, Element printedArg, PathNode sourceNode, PathNode sinkNode +where taintedWithPath(query, printedArg, sourceNode, sinkNode) +select printedArg, sourceNode, sinkNode, "Cross-site scripting vulnerability due to $@.", query, + "this query data" diff --git a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql index 3f234dd0678..de786d22f30 100644 --- a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -3,7 +3,7 @@ * @description Including user-supplied data in a SQL query without * neutralizing special elements can make code vulnerable * to SQL Injection. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cpp/sql-injection @@ -15,6 +15,7 @@ import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.TaintTracking +import TaintedWithPath class SQLLikeFunction extends FunctionWithWrappers { SQLLikeFunction() { sqlArgument(this.getName(), _) } @@ -22,11 +23,19 @@ class SQLLikeFunction extends FunctionWithWrappers { override predicate interestingArg(int arg) { sqlArgument(this.getName(), arg) } } -from SQLLikeFunction runSql, Expr taintedArg, Expr taintSource, string taintCause, string callChain +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(SQLLikeFunction runSql | runSql.outermostWrapperFunctionCall(tainted, _)) + } +} + +from + SQLLikeFunction runSql, Expr taintedArg, Expr taintSource, PathNode sourceNode, PathNode sinkNode, + string taintCause, string callChain where runSql.outermostWrapperFunctionCall(taintedArg, callChain) and - tainted(taintSource, taintedArg) and + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and isUserInput(taintSource, taintCause) -select taintedArg, +select taintedArg, sourceNode, sinkNode, "This argument to a SQL query function is derived from $@ and then passed to " + callChain, taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql index 233fe34e6bf..943c13f9c5d 100644 --- a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql +++ b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql @@ -3,7 +3,7 @@ * @description Using externally controlled strings in a process * operation can allow an attacker to execute malicious * commands. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/uncontrolled-process-operation @@ -14,13 +14,24 @@ import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -from string processOperation, int processOperationArg, FunctionCall call, Expr arg, Element source +predicate isProcessOperationExplanation(Expr arg, string processOperation) { + exists(int processOperationArg, FunctionCall call | + isProcessOperationArgument(processOperation, processOperationArg) and + call.getTarget().getName() = processOperation and + call.getArgument(processOperationArg) = arg + ) +} + +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element arg) { isProcessOperationExplanation(arg, _) } +} + +from string processOperation, Expr arg, Expr source, PathNode sourceNode, PathNode sinkNode where - isProcessOperationArgument(processOperation, processOperationArg) and - call.getTarget().getName() = processOperation and - call.getArgument(processOperationArg) = arg and - tainted(source, arg) -select arg, + isProcessOperationExplanation(arg, processOperation) and + taintedWithPath(source, arg, sourceNode, sinkNode) +select arg, sourceNode, sinkNode, "The value of this argument may come from $@ and is being passed to " + processOperation, source, source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql index ff136d2c06b..f1a8b4e8544 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql @@ -2,7 +2,7 @@ * @name Unbounded write * @description Buffer write operations that do not control the length * of data written may overflow. - * @kind problem + * @kind path-problem * @problem.severity error * @precision medium * @id cpp/unbounded-write @@ -16,6 +16,7 @@ import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath /* * --- Summary of CWE-120 alerts --- @@ -54,32 +55,48 @@ predicate isUnboundedWrite(BufferWrite bw) { * } */ +/** + * Holds if `e` is a source buffer going into an unbounded write `bw` or a + * qualifier of (a qualifier of ...) such a source. + */ +predicate unboundedWriteSource(Expr e, BufferWrite bw) { + isUnboundedWrite(bw) and e = bw.getASource() + or + exists(FieldAccess fa | unboundedWriteSource(fa, bw) and e = fa.getQualifier()) +} + /* * --- user input reach --- */ -/** - * Identifies expressions that are potentially tainted with user - * input. Most of the work for this is actually done by the - * TaintTracking library. - */ -predicate tainted2(Expr expr, Expr inputSource, string inputCause) { - taintedIncludingGlobalVars(inputSource, expr, _) and - inputCause = inputSource.toString() - or - exists(Expr e | tainted2(e, inputSource, inputCause) | - // field accesses of a tainted struct are tainted - e = expr.(FieldAccess).getQualifier() - ) +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { unboundedWriteSource(tainted, _) } + + override predicate taintThroughGlobals() { any() } } /* * --- put it together --- */ -from BufferWrite bw, Expr inputSource, string inputCause +/* + * An unbounded write is, for example `strcpy(..., tainted)`. We're looking + * for a tainted source buffer of an unbounded write, where this source buffer + * is a sink in the taint-tracking analysis. + * + * In the case of `gets` and `scanf`, where the source buffer is implicit, the + * `BufferWrite` library reports the source buffer to be the same as the + * destination buffer. Since those destination-buffer arguments are also + * modeled in the taint-tracking library as being _sources_ of taint, they are + * in practice reported as being tainted because the `security.TaintTracking` + * library does not distinguish between taint going into an argument and out of + * an argument. Thus, we get the desired alerts. + */ + +from BufferWrite bw, Expr inputSource, Expr tainted, PathNode sourceNode, PathNode sinkNode where - isUnboundedWrite(bw) and - tainted2(bw.getASource(), inputSource, inputCause) -select bw, "This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.", - inputSource, inputCause + taintedWithPath(inputSource, tainted, sourceNode, sinkNode) and + unboundedWriteSource(tainted, bw) +select bw, sourceNode, sinkNode, + "This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.", inputSource, + inputSource.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql index 19bee24a16d..80b5ee49e97 100644 --- a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql +++ b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql @@ -3,7 +3,7 @@ * @description Authentication by checking that the peer's address * matches a known IP or web address is unsafe as it is * vulnerable to spoofing attacks. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/user-controlled-bypass @@ -12,6 +12,7 @@ */ import semmle.code.cpp.security.TaintTracking +import TaintedWithPath predicate hardCodedAddressOrIP(StringLiteral txt) { exists(string s | s = txt.getValueText() | @@ -102,16 +103,21 @@ predicate useOfHardCodedAddressOrIP(Expr use) { * untrusted input then it might be vulnerable to a spoofing * attack. */ -predicate hardCodedAddressInCondition(Expr source, Expr condition) { - // One of the sub-expressions of the condition is tainted. - exists(Expr taintedExpr | taintedExpr.getParent+() = condition | tainted(source, taintedExpr)) and +predicate hardCodedAddressInCondition(Expr subexpression, Expr condition) { + subexpression = condition.getAChild+() and // One of the sub-expressions of the condition is a hard-coded // IP or web-address. - exists(Expr use | use.getParent+() = condition | useOfHardCodedAddressOrIP(use)) and + exists(Expr use | use = condition.getAChild+() | useOfHardCodedAddressOrIP(use)) and condition = any(IfStmt ifStmt).getCondition() } -from Expr source, Expr condition -where hardCodedAddressInCondition(source, condition) -select condition, "Untrusted input $@ might be vulnerable to a spoofing attack.", source, - source.toString() +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element sink) { hardCodedAddressInCondition(sink, _) } +} + +from Expr subexpression, Expr source, Expr condition, PathNode sourceNode, PathNode sinkNode +where + hardCodedAddressInCondition(subexpression, condition) and + taintedWithPath(source, subexpression, sourceNode, sinkNode) +select condition, sourceNode, sinkNode, + "Untrusted input $@ might be vulnerable to a spoofing attack.", source, source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index aa153779df1..3e84c0a87d9 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -2,7 +2,7 @@ * @name Cleartext storage of sensitive information in buffer * @description Storing sensitive information in cleartext can expose it * to an attacker. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/cleartext-storage-buffer @@ -14,12 +14,20 @@ import cpp import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.TaintTracking import semmle.code.cpp.security.SensitiveExprs +import TaintedWithPath -from BufferWrite w, Expr taintedArg, Expr taintSource, string taintCause, SensitiveExpr dest +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { exists(BufferWrite w | w.getASource() = tainted) } +} + +from + BufferWrite w, Expr taintedArg, Expr taintSource, PathNode sourceNode, PathNode sinkNode, + string taintCause, SensitiveExpr dest where - tainted(taintSource, taintedArg) and + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and isUserInput(taintSource, taintCause) and w.getASource() = taintedArg and dest = w.getDest() -select w, "This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@", +select w, sourceNode, sinkNode, + "This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@", taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql index b940da029ec..e60f592b2af 100644 --- a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql +++ b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql @@ -3,7 +3,7 @@ * @description Using untrusted inputs in a statement that makes a * security decision makes code vulnerable to * attack. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/tainted-permissions-check @@ -12,14 +12,9 @@ */ import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -/** - * Holds if there is an 'if' statement whose condition `condition` - * is influenced by tainted data `source`, and the body contains - * `raise` which escalates privilege. - */ -predicate cwe807violation(Expr source, Expr condition, Expr raise) { - tainted(source, condition) and +predicate sensitiveCondition(Expr condition, Expr raise) { raisesPrivilege(raise) and exists(IfStmt ifstmt | ifstmt.getCondition() = condition and @@ -27,7 +22,19 @@ predicate cwe807violation(Expr source, Expr condition, Expr raise) { ) } -from Expr source, Expr condition, Expr raise -where cwe807violation(source, condition, raise) -select condition, "Reliance on untrusted input $@ to raise privilege at $@", source, - source.toString(), raise, raise.toString() +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { sensitiveCondition(tainted, _) } +} + +/* + * Produce an alert if there is an 'if' statement whose condition `condition` + * is influenced by tainted data `source`, and the body contains + * `raise` which escalates privilege. + */ + +from Expr source, Expr condition, Expr raise, PathNode sourceNode, PathNode sinkNode +where + taintedWithPath(source, condition, sourceNode, sinkNode) and + sensitiveCondition(condition, raise) +select condition, sourceNode, sinkNode, "Reliance on untrusted input $@ to raise privilege at $@", + source, source.toString(), raise, raise.toString() diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected index bfdbb13a097..17bb67fdc08 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected @@ -1,2 +1,30 @@ -| search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | -| search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | +edges +| search.c:14:24:14:28 | query | search.c:17:8:17:12 | (const char *)... | +| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query | +| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query | +| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query | +| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query | +| search.c:41:21:41:26 | call to getenv | search.c:45:17:45:25 | raw_query | +| search.c:41:21:41:26 | call to getenv | search.c:45:17:45:25 | raw_query | +| search.c:41:21:41:26 | call to getenv | search.c:47:17:47:25 | raw_query | +| search.c:41:21:41:26 | call to getenv | search.c:47:17:47:25 | raw_query | +| search.c:45:17:45:25 | raw_query | search.c:14:24:14:28 | query | +| search.c:47:17:47:25 | raw_query | search.c:22:24:22:28 | query | +nodes +| search.c:14:24:14:28 | query | semmle.label | query | +| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | +| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | +| search.c:17:8:17:12 | query | semmle.label | query | +| search.c:17:8:17:12 | query | semmle.label | query | +| search.c:17:8:17:12 | query | semmle.label | query | +| search.c:22:24:22:28 | query | semmle.label | query | +| search.c:23:39:23:43 | query | semmle.label | query | +| search.c:23:39:23:43 | query | semmle.label | query | +| search.c:23:39:23:43 | query | semmle.label | query | +| search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | +| search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | +| search.c:45:17:45:25 | raw_query | semmle.label | raw_query | +| search.c:47:17:47:25 | raw_query | semmle.label | raw_query | +#select +| search.c:17:8:17:12 | query | search.c:41:21:41:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | +| search.c:23:39:23:43 | query | search.c:41:21:41:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index b494196d4aa..f84c6719157 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -1,2 +1,25 @@ -| test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:42:18:42:23 | call to getenv | call to getenv | -| test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:43:18:43:23 | call to getenv | call to getenv | +edges +| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command | +| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command | +| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command | +| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command | +| test.cpp:42:18:42:23 | call to getenv | test.cpp:24:30:24:36 | command | +| test.cpp:42:18:42:34 | (const char *)... | test.cpp:24:30:24:36 | command | +| test.cpp:43:18:43:23 | call to getenv | test.cpp:29:30:29:36 | command | +| test.cpp:43:18:43:34 | (const char *)... | test.cpp:29:30:29:36 | command | +nodes +| test.cpp:24:30:24:36 | command | semmle.label | command | +| test.cpp:26:10:26:16 | command | semmle.label | command | +| test.cpp:26:10:26:16 | command | semmle.label | command | +| test.cpp:26:10:26:16 | command | semmle.label | command | +| test.cpp:29:30:29:36 | command | semmle.label | command | +| test.cpp:31:10:31:16 | command | semmle.label | command | +| test.cpp:31:10:31:16 | command | semmle.label | command | +| test.cpp:31:10:31:16 | command | semmle.label | command | +| test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:42:18:42:34 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:43:18:43:34 | (const char *)... | semmle.label | (const char *)... | +#select +| test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:42:18:42:23 | call to getenv | call to getenv | +| test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system | test.cpp:43:18:43:23 | call to getenv | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected index e69de29bb2d..58e3dda0964 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected @@ -0,0 +1,3 @@ +edges +nodes +#select diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected index 5096e75ebc3..291c1cb3a71 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected @@ -1,5 +1,53 @@ -| tests.c:28:3:28:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | -| tests.c:29:3:29:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | -| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 | -| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:33:21:33:29 | buffer100 | buffer100 | -| tests.c:34:25:34:33 | buffer100 | This 'sscanf string argument' with input from $@ may overflow the destination. | tests.c:34:10:34:13 | argv | argv | +edges +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | (const char *)... | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | (const char *)... | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +nodes +| tests.c:28:22:28:25 | argv | semmle.label | argv | +| tests.c:28:22:28:25 | argv | semmle.label | argv | +| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... | +| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... | +| tests.c:28:22:28:28 | access to array | semmle.label | access to array | +| tests.c:28:22:28:28 | access to array | semmle.label | access to array | +| tests.c:28:22:28:28 | access to array | semmle.label | access to array | +| tests.c:29:28:29:31 | argv | semmle.label | argv | +| tests.c:29:28:29:31 | argv | semmle.label | argv | +| tests.c:29:28:29:34 | access to array | semmle.label | access to array | +| tests.c:29:28:29:34 | access to array | semmle.label | access to array | +| tests.c:29:28:29:34 | access to array | semmle.label | access to array | +| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | +| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | +| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | +| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | +| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | +| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | +| tests.c:34:10:34:13 | argv | semmle.label | argv | +| tests.c:34:10:34:13 | argv | semmle.label | argv | +| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | +| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | +| tests.c:34:10:34:16 | access to array | semmle.label | access to array | +| tests.c:34:10:34:16 | access to array | semmle.label | access to array | +| tests.c:34:10:34:16 | access to array | semmle.label | access to array | +#select +| tests.c:28:3:28:9 | call to sprintf | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | +| tests.c:29:3:29:9 | call to sprintf | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | +| tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 | +| tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:33:21:33:29 | buffer100 | buffer100 | +| tests.c:34:25:34:33 | buffer100 | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | This 'sscanf string argument' with input from $@ may overflow the destination. | tests.c:34:10:34:13 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected index ded1524cfca..e2671c07952 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected @@ -1,3 +1,33 @@ -| test.cpp:20:7:20:12 | call to strcmp | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:16:25:16:30 | call to getenv | call to getenv | -| test.cpp:31:7:31:12 | call to strcmp | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:27:25:27:30 | call to getenv | call to getenv | -| test.cpp:42:7:42:12 | call to strcmp | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:38:25:38:30 | call to getenv | call to getenv | +edges +| test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | +| test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | +| test.cpp:16:25:16:42 | (const char *)... | test.cpp:20:14:20:20 | address | +| test.cpp:16:25:16:42 | (const char *)... | test.cpp:20:14:20:20 | address | +| test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | +| test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | +| test.cpp:27:25:27:42 | (const char *)... | test.cpp:31:14:31:20 | address | +| test.cpp:27:25:27:42 | (const char *)... | test.cpp:31:14:31:20 | address | +| test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | +| test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | +| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address | +| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address | +nodes +| test.cpp:16:25:16:30 | call to getenv | semmle.label | call to getenv | +| test.cpp:16:25:16:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:20:14:20:20 | address | semmle.label | address | +| test.cpp:20:14:20:20 | address | semmle.label | address | +| test.cpp:20:14:20:20 | address | semmle.label | address | +| test.cpp:27:25:27:30 | call to getenv | semmle.label | call to getenv | +| test.cpp:27:25:27:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:31:14:31:20 | address | semmle.label | address | +| test.cpp:31:14:31:20 | address | semmle.label | address | +| test.cpp:31:14:31:20 | address | semmle.label | address | +| test.cpp:38:25:38:30 | call to getenv | semmle.label | call to getenv | +| test.cpp:38:25:38:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:42:14:42:20 | address | semmle.label | address | +| test.cpp:42:14:42:20 | address | semmle.label | address | +| test.cpp:42:14:42:20 | address | semmle.label | address | +#select +| test.cpp:20:7:20:12 | call to strcmp | test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:16:25:16:30 | call to getenv | call to getenv | +| test.cpp:31:7:31:12 | call to strcmp | test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:27:25:27:30 | call to getenv | call to getenv | +| test.cpp:42:7:42:12 | call to strcmp | test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:38:25:38:30 | call to getenv | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected index 30b971f13e7..f78d75eeed1 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected @@ -1 +1,13 @@ -| test.cpp:58:3:58:9 | call to sprintf | This write into buffer 'passwd' may contain unencrypted data from $@ | test.cpp:54:17:54:20 | argv | user input (argv) | +edges +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +nodes +| test.cpp:54:17:54:20 | argv | semmle.label | argv | +| test.cpp:54:17:54:20 | argv | semmle.label | argv | +| test.cpp:58:25:58:29 | input | semmle.label | input | +| test.cpp:58:25:58:29 | input | semmle.label | input | +| test.cpp:58:25:58:29 | input | semmle.label | input | +#select +| test.cpp:58:3:58:9 | call to sprintf | test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | This write into buffer 'passwd' may contain unencrypted data from $@ | test.cpp:54:17:54:20 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected index 0ae48831c80..cc5004047cf 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected @@ -1,2 +1,37 @@ -| test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... | -| test.cpp:41:10:41:38 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:42:8:42:26 | ... = ... | ... = ... | +edges +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:35 | (bool)... | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:10:41:38 | ! ... | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:11:41:38 | (bool)... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:10:24:35 | ! ... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:35 | (bool)... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:10:41:38 | ! ... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:11:41:38 | (bool)... | +| test.cpp:24:11:24:16 | call to strcmp | test.cpp:24:10:24:35 | ! ... | +| test.cpp:24:11:24:16 | call to strcmp | test.cpp:24:11:24:35 | (bool)... | +| test.cpp:41:11:41:16 | call to strcmp | test.cpp:41:10:41:38 | ! ... | +| test.cpp:41:11:41:16 | call to strcmp | test.cpp:41:11:41:38 | (bool)... | +nodes +| test.cpp:20:29:20:34 | call to getenv | semmle.label | call to getenv | +| test.cpp:20:29:20:47 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:24:10:24:35 | ! ... | semmle.label | ! ... | +| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:24:11:24:35 | (bool)... | semmle.label | (bool)... | +| test.cpp:24:11:24:35 | (bool)... | semmle.label | (bool)... | +| test.cpp:41:10:41:38 | ! ... | semmle.label | ! ... | +| test.cpp:41:11:41:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:41:11:41:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:41:11:41:38 | (bool)... | semmle.label | (bool)... | +| test.cpp:41:11:41:38 | (bool)... | semmle.label | (bool)... | +#select +| test.cpp:24:10:24:35 | ! ... | test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... | +| test.cpp:41:10:41:38 | ! ... | test.cpp:20:29:20:34 | call to getenv | test.cpp:41:10:41:38 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:42:8:42:26 | ... = ... | ... = ... | From bb3616e4c4cfc0ef6f2c8c5f65045acd4ef1326b Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 3 Apr 2020 17:51:35 +0200 Subject: [PATCH 307/459] C++: Add example for globalVarFromId --- .../semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 893de1c2af9..2cec0dc2a5a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -400,7 +400,14 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global /** * Gets the global variable whose qualified name is `id`. Use this predicate - * together with `taintedIncludingGlobalVars`. + * together with `taintedIncludingGlobalVars`. Example: + * + * ``` + * exists(string varName | + * taintedIncludingGlobalVars(source, tainted, varName) and + * var = globalVarFromId(varName) + * ) + * ``` */ GlobalOrNamespaceVariable globalVarFromId(string id) { id = result.getQualifiedName() } From 64b17888e52070d056d9387cd71d0270bb2faaca Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 3 Apr 2020 15:14:25 -0700 Subject: [PATCH 308/459] Python: ObjectAPI to ValueAPI: IterReturnsNonSelf: ObjectAPI.qll: Reorganizes getAnInferredReturnType() --- .../ql/src/semmle/python/objects/ObjectAPI.qll | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 2f39d8db16d..3ad8a877898 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -606,11 +606,7 @@ abstract class FunctionValue extends CallableValue { } /** Gets a class that this function may return */ - ClassValue getAnInferredReturnType() { - result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType()) - or - result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType()) - } + abstract ClassValue getAnInferredReturnType(); } /** Class representing Python functions */ @@ -639,6 +635,10 @@ class PythonFunctionValue extends FunctionValue { /** Gets a control flow node corresponding to a return statement in this function */ ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() } + + override ClassValue getAnInferredReturnType() { + result = this.getAReturnedNode().pointsTo().getClass() + } } /** Class representing builtin functions, such as `len` or `print` */ @@ -650,6 +650,10 @@ class BuiltinFunctionValue extends FunctionValue { override int minParameters() { none() } override int maxParameters() { none() } + + override ClassValue getAnInferredReturnType() { + result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType()) + } } /** Class representing builtin methods, such as `list.append` or `set.add` */ @@ -667,6 +671,10 @@ class BuiltinMethodValue extends FunctionValue { override int minParameters() { none() } override int maxParameters() { none() } + + override ClassValue getAnInferredReturnType() { + result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType()) + } } /** From be86c9c0667a415b704e9eb05963009fe213e686 Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Fri, 3 Apr 2020 15:16:16 -0700 Subject: [PATCH 309/459] Python: ObjectAPI to ValueAPI: IterReturnsNonSelf: ObjectAPI.qll: Explains why getAnInferredReturnType is weird for builtins --- python/ql/src/semmle/python/objects/ObjectAPI.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 3ad8a877898..9772a77ed8b 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -637,6 +637,9 @@ class PythonFunctionValue extends FunctionValue { ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() } override ClassValue getAnInferredReturnType() { + /* We have to do a special version of this because builtin functions have no + * explicit return nodes that we can query and get the class of. + */ result = this.getAReturnedNode().pointsTo().getClass() } } @@ -652,6 +655,9 @@ class BuiltinFunctionValue extends FunctionValue { override int maxParameters() { none() } override ClassValue getAnInferredReturnType() { + /* We have to do a special version of this because builtin functions have no + * explicit return nodes that we can query and get the class of. + */ result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType()) } } From 108d5177b8d2ebcb96b390874031afef1ee6c4c8 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sat, 4 Apr 2020 15:14:24 +0200 Subject: [PATCH 310/459] C++: Fix two bugs found by @rdmarsh2 Co-Authored-By: Robert Marsh --- .../CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql | 2 +- cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql index 88341f7ca9d..96cffdb024b 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql @@ -34,6 +34,6 @@ where not taintedWithoutGlobals(arg) and taintedWithPath(userValue, arg, sourceNode, sinkNode) and isUserInput(userValue, cause) -select arg, +select arg, sourceNode, sinkNode, "The value of this argument may come from $@ and is being used as a formatting argument to " + printfFunction, userValue, cause diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index c291246a774..87cb741b18b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -489,7 +489,7 @@ module TaintedWithPath { } } - private class WrapPathNode extends PathNode, TPathNode { + private class WrapPathNode extends PathNode, TWrapPathNode { DataFlow3::PathNode inner() { this = TWrapPathNode(result) } override string toString() { result = this.inner().toString() } From d7332644f0b6fb43d5a5ded33d9fdbfbd24749b5 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sat, 4 Apr 2020 15:31:01 +0200 Subject: [PATCH 311/459] C++: Fix DefinitionByReferenceNode.toString This predicate now has a value also for calls to function pointers. --- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 642180d0c2c..193173da442 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -246,6 +246,9 @@ class DefinitionByReferenceNode extends InstructionNode { result = instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget().getName() + " output argument" + or + not exists(instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget()) and + result = "output argument" } } From 54a23a486aa93480448aeab85022aa8a5959354a Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sat, 4 Apr 2020 16:46:18 +0200 Subject: [PATCH 312/459] C++: Accept test changes for 108d5177b8 --- .../UncontrolledFormatStringThroughGlobalVar.expected | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index 263399b2af8..ba735a3e140 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -58,8 +58,8 @@ nodes | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | #select -| globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:38:9:38:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:41:15:41:19 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:50:9:50:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | From 58366b19e920fdbb36c2e10469ff7707b0727829 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sat, 4 Apr 2020 16:39:08 +0200 Subject: [PATCH 313/459] C++: Path explanations in the last two queries For some reason I thought that these two queries were special because they manipulate `SecurityOptions` to change the taint-tracking sources. It turns out it was just the opposite: the queries used to be special because they invalidated the cache for the `tainted` predicate, but that predicate is no longer used, so these queries are no longer special. --- .../CWE/CWE-190/ArithmeticUncontrolled.ql | 44 ++++--- .../CWE/CWE-313/CleartextSqliteDatabase.ql | 24 +++- .../ArithmeticUncontrolled.expected | 121 ++++++++++++++++-- 3 files changed, 158 insertions(+), 31 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index 8013fbcf614..a4b0f131d14 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -2,7 +2,7 @@ * @name Uncontrolled data in arithmetic expression * @description Arithmetic operations on uncontrolled data that is not * validated can cause overflows. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/uncontrolled-arithmetic @@ -15,6 +15,7 @@ import cpp import semmle.code.cpp.security.Overflow import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath predicate isRandCall(FunctionCall fc) { fc.getTarget().getName() = "rand" } @@ -40,9 +41,22 @@ class SecurityOptionsArith extends SecurityOptions { } } -predicate taintedVarAccess(Expr origin, VariableAccess va) { - isUserInput(origin, _) and - tainted(origin, va) +predicate isDiv(VariableAccess va) { exists(AssignDivExpr div | div.getLValue() = va) } + +predicate missingGuard(VariableAccess va, string effect) { + exists(Operation op | op.getAnOperand() = va | + missingGuardAgainstUnderflow(op, va) and effect = "underflow" + or + missingGuardAgainstOverflow(op, va) and effect = "overflow" + ) +} + +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element e) { + isDiv(e) + or + missingGuard(e, _) + } } /** @@ -50,19 +64,17 @@ predicate taintedVarAccess(Expr origin, VariableAccess va) { * range. */ predicate guardedByAssignDiv(Expr origin) { - isUserInput(origin, _) and - exists(AssignDivExpr div, VariableAccess va | tainted(origin, va) and div.getLValue() = va) + exists(VariableAccess va | + taintedWithPath(origin, va, _, _) and + isDiv(va) + ) } -from Expr origin, Operation op, VariableAccess va, string effect +from Expr origin, VariableAccess va, string effect, PathNode sourceNode, PathNode sinkNode where - taintedVarAccess(origin, va) and - op.getAnOperand() = va and - ( - missingGuardAgainstUnderflow(op, va) and effect = "underflow" - or - missingGuardAgainstOverflow(op, va) and effect = "overflow" - ) and + taintedWithPath(origin, va, sourceNode, sinkNode) and + missingGuard(va, effect) and not guardedByAssignDiv(origin) -select va, "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", - origin, "Uncontrolled value" +select va, sourceNode, sinkNode, + "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", origin, + "Uncontrolled value" diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index e4f1e9c834a..000833cbb58 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -2,7 +2,7 @@ * @name Cleartext storage of sensitive information in an SQLite database * @description Storing sensitive information in a non-encrypted * database can expose it to an attacker. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/cleartext-storage-database @@ -13,6 +13,7 @@ import cpp import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.security.TaintTracking +import TaintedWithPath class UserInputIsSensitiveExpr extends SecurityOptions { override predicate isUserInput(Expr expr, string cause) { @@ -32,10 +33,21 @@ predicate sqlite_encryption_used() { any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%") } -from SensitiveExpr taintSource, Expr taintedArg, SqliteFunctionCall sqliteCall +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element taintedArg) { + exists(SqliteFunctionCall sqliteCall | + taintedArg = sqliteCall.getASource() and + not sqlite_encryption_used() + ) + } +} + +from + SensitiveExpr taintSource, Expr taintedArg, SqliteFunctionCall sqliteCall, PathNode sourceNode, + PathNode sinkNode where - tainted(taintSource, taintedArg) and - taintedArg = sqliteCall.getASource() and - not sqlite_encryption_used() -select sqliteCall, "This SQLite call may store $@ in a non-encrypted SQLite database", taintSource, + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and + taintedArg = sqliteCall.getASource() +select sqliteCall, sourceNode, sinkNode, + "This SQLite call may store $@ in a non-encrypted SQLite database", taintSource, "sensitive information" diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected index 860ef74fdff..461625d8b77 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected @@ -1,9 +1,112 @@ -| test.c:21:17:21:17 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | Uncontrolled value | -| test.c:35:5:35:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | Uncontrolled value | -| test.c:40:5:40:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:39:13:39:21 | ... % ... | Uncontrolled value | -| test.c:45:5:45:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | Uncontrolled value | -| test.c:56:5:56:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:54:13:54:16 | call to rand | Uncontrolled value | -| test.c:67:5:67:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:66:13:66:16 | call to rand | Uncontrolled value | -| test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value | -| test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value | -| test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value | +edges +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.cpp:8:9:8:12 | Store | test.cpp:24:11:24:18 | call to get_rand | +| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store | +| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store | +| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r | +| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r | +nodes +| test.c:18:13:18:16 | call to rand | semmle.label | call to rand | +| test.c:18:13:18:16 | call to rand | semmle.label | call to rand | +| test.c:21:17:21:17 | r | semmle.label | r | +| test.c:21:17:21:17 | r | semmle.label | r | +| test.c:21:17:21:17 | r | semmle.label | r | +| test.c:34:13:34:18 | call to rand | semmle.label | call to rand | +| test.c:34:13:34:18 | call to rand | semmle.label | call to rand | +| test.c:35:5:35:5 | r | semmle.label | r | +| test.c:35:5:35:5 | r | semmle.label | r | +| test.c:35:5:35:5 | r | semmle.label | r | +| test.c:39:13:39:21 | ... % ... | semmle.label | ... % ... | +| test.c:39:13:39:21 | ... % ... | semmle.label | ... % ... | +| test.c:40:5:40:5 | r | semmle.label | r | +| test.c:40:5:40:5 | r | semmle.label | r | +| test.c:40:5:40:5 | r | semmle.label | r | +| test.c:44:13:44:16 | call to rand | semmle.label | call to rand | +| test.c:44:13:44:16 | call to rand | semmle.label | call to rand | +| test.c:45:5:45:5 | r | semmle.label | r | +| test.c:45:5:45:5 | r | semmle.label | r | +| test.c:45:5:45:5 | r | semmle.label | r | +| test.c:54:13:54:16 | call to rand | semmle.label | call to rand | +| test.c:54:13:54:16 | call to rand | semmle.label | call to rand | +| test.c:56:5:56:5 | r | semmle.label | r | +| test.c:56:5:56:5 | r | semmle.label | r | +| test.c:56:5:56:5 | r | semmle.label | r | +| test.c:60:13:60:16 | call to rand | semmle.label | call to rand | +| test.c:60:13:60:16 | call to rand | semmle.label | call to rand | +| test.c:61:5:61:5 | r | semmle.label | r | +| test.c:61:5:61:5 | r | semmle.label | r | +| test.c:61:5:61:5 | r | semmle.label | r | +| test.c:62:5:62:5 | r | semmle.label | r | +| test.c:62:5:62:5 | r | semmle.label | r | +| test.c:62:5:62:5 | r | semmle.label | r | +| test.c:66:13:66:16 | call to rand | semmle.label | call to rand | +| test.c:66:13:66:16 | call to rand | semmle.label | call to rand | +| test.c:67:5:67:5 | r | semmle.label | r | +| test.c:67:5:67:5 | r | semmle.label | r | +| test.c:67:5:67:5 | r | semmle.label | r | +| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... | +| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... | +| test.c:77:9:77:9 | r | semmle.label | r | +| test.c:77:9:77:9 | r | semmle.label | r | +| test.c:77:9:77:9 | r | semmle.label | r | +| test.c:99:14:99:19 | call to rand | semmle.label | call to rand | +| test.c:99:14:99:19 | call to rand | semmle.label | call to rand | +| test.c:100:5:100:5 | r | semmle.label | r | +| test.c:100:5:100:5 | r | semmle.label | r | +| test.c:100:5:100:5 | r | semmle.label | r | +| test.cpp:8:9:8:12 | Store | semmle.label | Store | +| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand | +| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand | +| test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand | +| test.cpp:25:7:25:7 | r | semmle.label | r | +| test.cpp:25:7:25:7 | r | semmle.label | r | +| test.cpp:25:7:25:7 | r | semmle.label | r | +#select +| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | Uncontrolled value | +| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | Uncontrolled value | +| test.c:40:5:40:5 | r | test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:39:13:39:21 | ... % ... | Uncontrolled value | +| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | Uncontrolled value | +| test.c:56:5:56:5 | r | test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:54:13:54:16 | call to rand | Uncontrolled value | +| test.c:67:5:67:5 | r | test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:66:13:66:16 | call to rand | Uncontrolled value | +| test.c:77:9:77:9 | r | test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value | +| test.c:100:5:100:5 | r | test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value | +| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value | From 317734f41e011f73794fa740aaa62843467ae553 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Sun, 5 Apr 2020 22:35:26 +0200 Subject: [PATCH 314/459] C++: Attach PostUpdateNodes to Chi nodes following aschackmull's suggestion --- .../ir/dataflow/internal/DataFlowPrivate.qll | 6 +- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 61 +++++++------- .../dataflow/fields/ir-flow.expected | 80 ------------------- 3 files changed, 31 insertions(+), 116 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index c80982bd4d5..5d99866e7ea 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -148,10 +148,10 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { */ predicate readStep(Node node1, Content f, Node node2) { exists(FieldAddressInstruction fa, LoadInstruction load | - load.getSourceAddress() = fa and - node1.asInstruction() = fa.getObjectAddress() and fa.getField() = f.(FieldContent).getField() and - load = node2.asInstruction() + node1.asInstruction() = load and + load.getSourceAddress() = fa and + node2.asInstruction().getAnOperand().getAnyDef() = load ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 5eba5108983..018901eb946 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -245,30 +245,19 @@ abstract class PostUpdateNode extends InstructionNode { * setY(&x); // a partial definition of the object `x`. * ``` */ -abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { - /** - * Gets the instruction that partially defines the object. This includes - * both the instruction that partially defines the object, and the chi - * instruction that links up the partial definition to the object. - */ - final Instruction getInstructionOrChi() { - exists(ChiInstruction chi | - not chi.isResultConflated() and - chi.getPartial() = getInstruction() and - result = chi - ) - or - result = getInstruction() - } -} +abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {} private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { - override StoreInstruction instr; - FieldAddressInstruction field; + override ChiInstruction instr; - ExplicitFieldStoreQualifierNode() { field = instr.getDestinationAddress() } + ExplicitFieldStoreQualifierNode() { + not instr.isResultConflated() and + exists(StoreInstruction store, FieldInstruction field | + instr.getPartial() = store and field = store.getDestinationAddress() + ) + } - override Node getPreUpdateNode() { result.asInstruction() = field.getObjectAddress() } + override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } } /** @@ -282,29 +271,29 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { * `getVariableAccess()` equal to `x`. */ class DefinitionByReferenceNode extends PartialDefinitionNode { - override WriteSideEffectInstruction instr; + override ChiInstruction instr; + WriteSideEffectInstruction write; CallInstruction call; - DefinitionByReferenceNode() { call = instr.getPrimaryInstruction() } + DefinitionByReferenceNode() { + instr.getPartial() = write and + call = write.getPrimaryInstruction() } override Node getPreUpdateNode() { - result.asInstruction() = call.getPositionalArgument(instr.getIndex()) - or - result.asInstruction() = call.getThisArgument() and - instr.getIndex() = -1 + result.asInstruction() = instr.getTotal() } /** Gets the argument corresponding to this node. */ Expr getArgument() { - result = call.getPositionalArgument(instr.getIndex()).getUnconvertedResultExpression() + result = call.getPositionalArgument(write.getIndex()).getUnconvertedResultExpression() or result = call.getThisArgument().getUnconvertedResultExpression() and - instr.getIndex() = -1 + write.getIndex() = -1 } /** Gets the parameter through which this value is assigned. */ Parameter getParameter() { - exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex())) + exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(write.getIndex())) } } @@ -393,10 +382,10 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) or - exists(LoadInstruction load | - load.getSourceValueOperand().getAnyDef() = - nodeFrom.(PartialDefinitionNode).getInstructionOrChi() and - nodeTo.asInstruction() = load.getSourceAddress().(FieldAddressInstruction).getObjectAddress() + exists(LoadInstruction load, ChiInstruction chi | + nodeTo.asInstruction() = load and + nodeFrom.asInstruction() = chi and + load.getSourceValueOperand().getAnyDef() = chi ) } @@ -423,6 +412,12 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // // Flow through the partial operand belongs in the taint-tracking libraries // for now. + + // TODO: To capture flow from a partial definition of an object (i.e., a field write) to the object + // we add dataflow through partial chi operands, but only if the chi node is not the chi node for all + // aliased memory. + iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom and not iFrom.isResultConflated() + or iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or // Flow through modeled functions diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index 3c7bbe96a7d..2503be80b00 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -1,107 +1,27 @@ edges -| aliasing.cpp:9:3:9:22 | Store : void | aliasing.cpp:9:3:9:22 | Store [m1] : void | -| aliasing.cpp:9:3:9:22 | Store [m1] : void | aliasing.cpp:25:17:25:19 | BufferMayWriteSideEffect [m1] : void | -| aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:9:3:9:22 | Store : void | -| aliasing.cpp:13:3:13:21 | Store : void | aliasing.cpp:13:3:13:21 | Store [m1] : void | -| aliasing.cpp:13:3:13:21 | Store [m1] : void | aliasing.cpp:26:19:26:20 | BufferMayWriteSideEffect [m1] : void | -| aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:13:3:13:21 | Store : void | -| aliasing.cpp:25:17:25:19 | BufferMayWriteSideEffect [m1] : void | aliasing.cpp:29:8:29:9 | s1 [m1] : void | -| aliasing.cpp:26:19:26:20 | BufferMayWriteSideEffect [m1] : void | aliasing.cpp:30:8:30:9 | s2 [m1] : void | -| aliasing.cpp:29:8:29:9 | s1 [m1] : void | aliasing.cpp:29:11:29:12 | m1 | -| aliasing.cpp:30:8:30:9 | s2 [m1] : void | aliasing.cpp:30:11:30:12 | m1 | -| aliasing.cpp:37:3:37:24 | Store : void | aliasing.cpp:37:3:37:24 | Store [m1] : void | -| aliasing.cpp:37:3:37:24 | Store : void | aliasing.cpp:38:11:38:12 | m1 | -| aliasing.cpp:37:3:37:24 | Store [m1] : void | aliasing.cpp:38:8:38:9 | s1 [m1] : void | -| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | Store : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | -| aliasing.cpp:38:8:38:9 | s1 [m1] : void | aliasing.cpp:38:11:38:12 | m1 | -| aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:42:3:42:22 | Store [m1] : void | -| aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:42:3:42:22 | Store [m1] : void | aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | -| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | Store : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:79:3:79:22 | Store [m1] : void | -| aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:80:12:80:13 | m1 | -| aliasing.cpp:79:3:79:22 | Store [m1] : void | aliasing.cpp:80:10:80:10 | s [m1] : void | -| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | Store : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | -| aliasing.cpp:80:10:80:10 | s [m1] : void | aliasing.cpp:80:12:80:13 | m1 | -| aliasing.cpp:86:3:86:21 | Store : void | aliasing.cpp:86:3:86:21 | Store [m1] : void | -| aliasing.cpp:86:3:86:21 | Store : void | aliasing.cpp:87:12:87:13 | m1 | -| aliasing.cpp:86:3:86:21 | Store [m1] : void | aliasing.cpp:87:10:87:10 | s [m1] : void | -| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | Store : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | -| aliasing.cpp:87:10:87:10 | s [m1] : void | aliasing.cpp:87:12:87:13 | m1 | -| aliasing.cpp:92:3:92:23 | Store : void | aliasing.cpp:92:3:92:23 | Store [m1] : void | -| aliasing.cpp:92:3:92:23 | Store : void | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:92:3:92:23 | Store [m1] : void | aliasing.cpp:93:10:93:10 | s [m1] : void | -| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | Store : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:93:10:93:10 | s [m1] : void | aliasing.cpp:93:12:93:13 | m1 | -| struct_init.c:20:20:20:29 | Store : void | struct_init.c:20:20:20:29 | Store [a] : void | -| struct_init.c:20:20:20:29 | Store : void | struct_init.c:22:11:22:11 | a | -| struct_init.c:20:20:20:29 | Store [a] : void | struct_init.c:22:8:22:9 | ab [a] : void | -| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | Store : void | | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | -| struct_init.c:22:8:22:9 | ab [a] : void | struct_init.c:22:11:22:11 | a | -| struct_init.c:27:7:27:16 | Store : void | struct_init.c:27:7:27:16 | Store [a] : void | -| struct_init.c:27:7:27:16 | Store : void | struct_init.c:31:23:31:23 | a | -| struct_init.c:27:7:27:16 | Store [a] : void | struct_init.c:31:14:31:21 | nestedAB [a] : void | -| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | Store : void | | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | -| struct_init.c:31:14:31:21 | nestedAB [a] : void | struct_init.c:31:23:31:23 | a | nodes -| aliasing.cpp:9:3:9:22 | Store : void | semmle.label | Store : void | -| aliasing.cpp:9:3:9:22 | Store [m1] : void | semmle.label | Store [m1] : void | -| aliasing.cpp:9:11:9:20 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:13:3:13:21 | Store : void | semmle.label | Store : void | -| aliasing.cpp:13:3:13:21 | Store [m1] : void | semmle.label | Store [m1] : void | -| aliasing.cpp:13:10:13:19 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:25:17:25:19 | BufferMayWriteSideEffect [m1] : void | semmle.label | BufferMayWriteSideEffect [m1] : void | -| aliasing.cpp:26:19:26:20 | BufferMayWriteSideEffect [m1] : void | semmle.label | BufferMayWriteSideEffect [m1] : void | -| aliasing.cpp:29:8:29:9 | s1 [m1] : void | semmle.label | s1 [m1] : void | -| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 | -| aliasing.cpp:30:8:30:9 | s2 [m1] : void | semmle.label | s2 [m1] : void | -| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | -| aliasing.cpp:37:3:37:24 | Store : void | semmle.label | Store : void | -| aliasing.cpp:37:3:37:24 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:38:8:38:9 | s1 [m1] : void | semmle.label | s1 [m1] : void | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | -| aliasing.cpp:42:3:42:22 | Store : void | semmle.label | Store : void | -| aliasing.cpp:42:3:42:22 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | semmle.label | (reference dereference) [m1] : void | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | -| aliasing.cpp:79:3:79:22 | Store : void | semmle.label | Store : void | -| aliasing.cpp:79:3:79:22 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:80:10:80:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | -| aliasing.cpp:86:3:86:21 | Store : void | semmle.label | Store : void | -| aliasing.cpp:86:3:86:21 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:87:10:87:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | -| aliasing.cpp:92:3:92:23 | Store : void | semmle.label | Store : void | -| aliasing.cpp:92:3:92:23 | Store [m1] : void | semmle.label | Store [m1] : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:93:10:93:10 | s [m1] : void | semmle.label | s [m1] : void | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | -| struct_init.c:20:20:20:29 | Store : void | semmle.label | Store : void | -| struct_init.c:20:20:20:29 | Store [a] : void | semmle.label | Store [a] : void | | struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void | -| struct_init.c:22:8:22:9 | ab [a] : void | semmle.label | ab [a] : void | | struct_init.c:22:11:22:11 | a | semmle.label | a | -| struct_init.c:27:7:27:16 | Store : void | semmle.label | Store : void | -| struct_init.c:27:7:27:16 | Store [a] : void | semmle.label | Store [a] : void | | struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void | -| struct_init.c:31:14:31:21 | nestedAB [a] : void | semmle.label | nestedAB [a] : void | | struct_init.c:31:23:31:23 | a | semmle.label | a | #select -| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input : void | call to user_input : void | -| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input : void | call to user_input : void | | aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void | | aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input : void | call to user_input : void | | aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input : void | call to user_input : void | From c8c706a0ba0692b0ce63ea12e7a70ff9d040d635 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 6 Apr 2020 09:00:04 +0200 Subject: [PATCH 315/459] C#: Un-deprecate `PublicCallableParameterFlowSource` --- .../flowsources/PublicCallableParameter.qll | 4 +--- .../PublicCallableParameterFlowSource.cs | 17 +++++++++++++++++ .../publicCallableParameterFlowSource.expected | 2 ++ .../publicCallableParameterFlowSource.ql | 5 +++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs create mode 100644 csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected create mode 100644 csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll index 7c6700c6637..cf69f54717a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll @@ -7,8 +7,6 @@ import csharp /** - * DEPRECATED. - * * A parameter of a public callable, for example `p` in * * ``` @@ -17,7 +15,7 @@ import csharp * } * ``` */ -deprecated class PublicCallableParameterFlowSource extends DataFlow::ParameterNode { +class PublicCallableParameterFlowSource extends DataFlow::ParameterNode { PublicCallableParameterFlowSource() { exists(Callable c, Parameter p | p = this.getParameter() and diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs new file mode 100644 index 00000000000..d4d8016974a --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/PublicCallableParameterFlowSource.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Specialized; + +class PublicCallableParameterFlowSource +{ + public void M1(string x, out string y, ref string z) + { + y = x; + y = z; + } + + void M2(string x, out string y, ref string z) + { + y = x; + y = z; + } +} diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected new file mode 100644 index 00000000000..8d80e68a16c --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.expected @@ -0,0 +1,2 @@ +| PublicCallableParameterFlowSource.cs:6:27:6:27 | x | +| PublicCallableParameterFlowSource.cs:6:55:6:55 | z | diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql new file mode 100644 index 00000000000..b5a6460a7ca --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/flowsources/publicparameter/publicCallableParameterFlowSource.ql @@ -0,0 +1,5 @@ +import semmle.code.csharp.dataflow.flowsources.PublicCallableParameter + +from PublicCallableParameterFlowSource source +where source.getParameter().fromSource() +select source From d2b0599b631854f63f80f047b16952eabf6a762e Mon Sep 17 00:00:00 2001 From: james Date: Mon, 6 Apr 2020 09:27:30 +0100 Subject: [PATCH 316/459] docs: combine table and footnotes --- docs/language/support/language-support.rst | 16 +--------- docs/language/support/versions-compilers.csv | 18 ----------- docs/language/support/versions-compilers.rst | 33 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 33 deletions(-) delete mode 100644 docs/language/support/versions-compilers.csv create mode 100644 docs/language/support/versions-compilers.rst diff --git a/docs/language/support/language-support.rst b/docs/language/support/language-support.rst index 1dea250d430..4ffd28f3797 100644 --- a/docs/language/support/language-support.rst +++ b/docs/language/support/language-support.rst @@ -10,18 +10,4 @@ Customers with any questions should contact their usual Semmle contact with any If you're not a customer yet, contact us at info@semmle.com with any questions you have about language and compiler support. -.. csv-table:: - :file: versions-compilers.csv - :header-rows: 1 - :widths: auto - :stub-columns: 1 - -.. container:: footnote-group - - .. [1] Support for the clang-cl compiler is preliminary. - .. [2] Support for the Arm Compiler (armcc) is preliminary. - .. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0. - .. [4] Builds that execute on Java 6 to 12 can be analyzed. The analysis understands Java 12 language features. - .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. - .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. - .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. +.. include:: versions-compilers.rst diff --git a/docs/language/support/versions-compilers.csv b/docs/language/support/versions-compilers.csv deleted file mode 100644 index 8b60f8ee3a9..00000000000 --- a/docs/language/support/versions-compilers.csv +++ /dev/null @@ -1,18 +0,0 @@ -Language,Variants,Compilers,Extensions -C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0), - -GNU extensions (up to GCC 9.2), - -Microsoft extensions (up to VS 2019), - -Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" -C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019, - -.NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" -Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go`` -Java,"Java 6 to 13 [4]_","javac (OpenJDK and Oracle JDK), - -Eclipse compiler for Java (ECJ) [5]_",``.java`` -JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" -Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py`` -TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``" diff --git a/docs/language/support/versions-compilers.rst b/docs/language/support/versions-compilers.rst new file mode 100644 index 00000000000..2f4091139ea --- /dev/null +++ b/docs/language/support/versions-compilers.rst @@ -0,0 +1,33 @@ +.. csv-table:: + :header-rows: 1 + :widths: auto + :stub-columns: 1 + + Language,Variants,Compilers,Extensions + C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0), + + GNU extensions (up to GCC 9.2), + + Microsoft extensions (up to VS 2019), + + Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" + C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019, + + .NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" + Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go`` + Java,"Java 6 to 13 [4]_","javac (OpenJDK and Oracle JDK), + + Eclipse compiler for Java (ECJ) [5]_",``.java`` + JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" + Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py`` + TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``" + +.. container:: footnote-group + + .. [1] Support for the clang-cl compiler is preliminary. + .. [2] Support for the Arm Compiler (armcc) is preliminary. + .. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0. + .. [4] Builds that execute on Java 6 to 12 can be analyzed. The analysis understands Java 12 language features. + .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. + .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. + .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. From 3aa293210d05cb5a52c60515cf018f87e836bb9b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 6 Apr 2020 12:02:56 +0200 Subject: [PATCH 317/459] C++: Ensure that only non-conflated chi instructions are used everywhere --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 018901eb946..49ff9a85ad5 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -245,7 +245,7 @@ abstract class PostUpdateNode extends InstructionNode { * setY(&x); // a partial definition of the object `x`. * ``` */ -abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {} +abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { } private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { override ChiInstruction instr; @@ -276,13 +276,13 @@ class DefinitionByReferenceNode extends PartialDefinitionNode { CallInstruction call; DefinitionByReferenceNode() { + not instr.isResultConflated() and instr.getPartial() = write and - call = write.getPrimaryInstruction() } - - override Node getPreUpdateNode() { - result.asInstruction() = instr.getTotal() + call = write.getPrimaryInstruction() } + override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } + /** Gets the argument corresponding to this node. */ Expr getArgument() { result = call.getPositionalArgument(write.getIndex()).getUnconvertedResultExpression() @@ -292,9 +292,7 @@ class DefinitionByReferenceNode extends PartialDefinitionNode { } /** Gets the parameter through which this value is assigned. */ - Parameter getParameter() { - exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(write.getIndex())) - } + Parameter getParameter() { result = call.getStaticCallTarget().getParameter(write.getIndex()) } } /** @@ -383,6 +381,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) or exists(LoadInstruction load, ChiInstruction chi | + not chi.isResultConflated() and nodeTo.asInstruction() = load and nodeFrom.asInstruction() = chi and load.getSourceValueOperand().getAnyDef() = chi @@ -412,11 +411,10 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // // Flow through the partial operand belongs in the taint-tracking libraries // for now. - // TODO: To capture flow from a partial definition of an object (i.e., a field write) to the object // we add dataflow through partial chi operands, but only if the chi node is not the chi node for all // aliased memory. - iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom and not iFrom.isResultConflated() + iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom and not iTo.isResultConflated() or iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or From 2c6beadf68df5f24cc6c395559b789495c3ee8bf Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 1 Apr 2020 14:03:03 +0100 Subject: [PATCH 318/459] JS: Recognize more forms of scheme checks --- change-notes/1.24/analysis-javascript.md | 1 + .../CWE-020/IncompleteUrlSchemeCheck.ql | 67 +++++++++++++++++-- .../CWE-020/IncompleteUrlSchemeCheck.expected | 6 +- .../CWE-020/IncompleteUrlSchemeCheck.js | 43 +++++++++++- 4 files changed, 108 insertions(+), 9 deletions(-) diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index 7c72ecea6b1..0e92d66033d 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -86,6 +86,7 @@ | Useless regular-expression character escape (`js/useless-regexp-character-escape`) | Fewer false positive results | This query now distinguishes escapes in strings and regular expression literals. | | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | +| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. | ## Changes to libraries diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql b/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql index 86ab1744086..7e329b94f5f 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql @@ -12,11 +12,50 @@ */ import javascript -import semmle.javascript.dataflow.internal.AccessPaths /** A URL scheme that can be used to represent executable code. */ class DangerousScheme extends string { DangerousScheme() { this = "data:" or this = "javascript:" or this = "vbscript:" } + + /** Gets the name of this scheme without the `:`. */ + string getWithoutColon() { + this = result + ":" + } + + /** Gets the name of this scheme, with or without the `:`. */ + string getWithOrWithoutColon() { + result = this or result = getWithoutColon() + } +} + +/** Returns a node that refers to the scheme of `url`. */ +DataFlow::SourceNode schemeOf(DataFlow::Node url) { + // url.split(":")[0] + exists(DataFlow::MethodCallNode split | + split.getMethodName() = "split" and + split.getArgument(0).getStringValue() = ":" and + result = split.getAPropertyRead("0") and + url = split.getReceiver() + ) + or + // url.getScheme(), url.getProtocol(), getScheme(url), getProtocol(url) + exists(DataFlow::CallNode call | + result = call and + (call.getCalleeName() = "getScheme" or call.getCalleeName() = "getProtocol") + | + call.getNumArgument() = 1 and + url = call.getArgument(0) + or + call.getNumArgument() = 0 and + url = call.getReceiver() + ) + or + // url.scheme, url.protocol + exists(DataFlow::PropRead prop | + result = prop and + (prop.getPropertyName() = "scheme" or prop.getPropertyName() = "protocol") and + url = prop.getBase() + ) } /** Gets a data-flow node that checks `nd` against the given `scheme`. */ @@ -27,6 +66,20 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) { sw.getSubstring().mayHaveStringValue(scheme) ) or + // check of the form `array.includes(getScheme(nd))` + exists(InclusionTest test, DataFlow::ArrayCreationNode array | test = result | + schemeOf(nd).flowsTo(test.getContainedNode()) and + array.flowsTo(test.getContainerNode()) and + array.getAnElement().mayHaveStringValue(scheme.getWithOrWithoutColon()) + ) + or + // check of the form `getScheme(nd) === scheme` + exists(EqualityTest test, Expr op1, Expr op2 | test.flow() = result | + test.hasOperands(op1, op2) and + schemeOf(nd).flowsToExpr(op1) and + op2.mayHaveStringValue(scheme.getWithOrWithoutColon()) + ) + or // propagate through trimming, case conversion, and regexp replace exists(DataFlow::MethodCallNode stringop | stringop.getMethodName().matches("trim%") or @@ -42,14 +95,14 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) { } /** Gets a data-flow node that checks an instance of `ap` against the given `scheme`. */ -DataFlow::Node schemeCheckOn(AccessPath ap, DangerousScheme scheme) { - result = schemeCheck(ap.getAnInstance().flow(), scheme) +DataFlow::Node schemeCheckOn(DataFlow::SourceNode root, string path, DangerousScheme scheme) { + result = schemeCheck(AccessPath::getAReferenceTo(root, path), scheme) } -from AccessPath ap, int n +from DataFlow::SourceNode root, string path, int n where n = strictcount(DangerousScheme s) and - strictcount(DangerousScheme s | exists(schemeCheckOn(ap, s))) < n -select schemeCheckOn(ap, "javascript:"), + strictcount(DangerousScheme s | exists(schemeCheckOn(root, path, s))) < n +select schemeCheckOn(root, path, "javascript:"), "This check does not consider " + - strictconcat(DangerousScheme s | not exists(schemeCheckOn(ap, s)) | s, " and ") + "." + strictconcat(DangerousScheme s | not exists(schemeCheckOn(root, path, s)) | s, " and ") + "." diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected index de7800f58fd..05b255fad02 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected @@ -1 +1,5 @@ -| IncompleteUrlSchemeCheck.js:3:9:3:35 | u.start ... ript:") | This check does not consider data: and vbscript:. | +| IncompleteUrlSchemeCheck.js:5:9:5:35 | u.start ... ript:") | This check does not consider data: and vbscript:. | +| IncompleteUrlSchemeCheck.js:16:9:16:39 | badProt ... otocol) | This check does not consider vbscript:. | +| IncompleteUrlSchemeCheck.js:23:9:23:43 | badProt ... scheme) | This check does not consider vbscript:. | +| IncompleteUrlSchemeCheck.js:30:9:30:43 | badProt ... scheme) | This check does not consider vbscript:. | +| IncompleteUrlSchemeCheck.js:37:9:37:31 | scheme ... script" | This check does not consider data: and vbscript:. | diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js index 270cff2d821..617bb224da9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js @@ -1,6 +1,47 @@ +import * as dummy from 'dummy'; + function sanitizeUrl(url) { let u = decodeURI(url).trim().toLowerCase(); - if (u.startsWith("javascript:")) + if (u.startsWith("javascript:")) // NOT OK + return "about:blank"; + return url; +} + +let badProtocols = ['javascript:', 'data:']; +let badProtocolNoColon = ['javascript', 'data']; +let badProtocolsGood = ['javascript:', 'data:', 'vbscript:']; + +function test2(url) { + let protocol = new URL(url).protocol; + if (badProtocols.includes(protocol)) // NOT OK + return "about:blank"; + return url; +} + +function test3(url) { + let scheme = goog.uri.utils.getScheme(url); + if (badProtocolNoColon.includes(scheme)) // NOT OK + return "about:blank"; + return url; +} + +function test4(url) { + let scheme = url.split(':')[0]; + if (badProtocolNoColon.includes(scheme)) // NOT OK + return "about:blank"; + return url; +} + +function test5(url) { + let scheme = url.split(':')[0]; + if (scheme === "javascript") // NOT OK + return "about:blank"; + return url; +} + +function test6(url) { + let protocol = new URL(url).protocol; + if (badProtocolsGood.includes(protocol)) // OK return "about:blank"; return url; } From 7da0345c6a686011cae84d990f1ed2ea8d194149 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 2 Apr 2020 09:45:49 +0100 Subject: [PATCH 319/459] JS: Autoformat --- .../ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql b/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql index 7e329b94f5f..0a9314382f2 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql @@ -18,14 +18,10 @@ class DangerousScheme extends string { DangerousScheme() { this = "data:" or this = "javascript:" or this = "vbscript:" } /** Gets the name of this scheme without the `:`. */ - string getWithoutColon() { - this = result + ":" - } + string getWithoutColon() { this = result + ":" } /** Gets the name of this scheme, with or without the `:`. */ - string getWithOrWithoutColon() { - result = this or result = getWithoutColon() - } + string getWithOrWithoutColon() { result = this or result = getWithoutColon() } } /** Returns a node that refers to the scheme of `url`. */ From 97cdcbee6388947c3a66da8a0cd5e6ec37d520b9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 13:52:16 +0100 Subject: [PATCH 320/459] C++: Test for NewFreeMismatch.ql with operator new / delete. --- .../Critical/NewFree/NewFreeMismatch.expected | 4 ++++ .../query-tests/Critical/NewFree/test2.cpp | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected index 7350749ce96..d588fc26e7b 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected @@ -1,5 +1,9 @@ | test2.cpp:19:3:19:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:18:12:18:18 | new | new | | test2.cpp:26:3:26:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:25:7:25:13 | new | new | +| test2.cpp:50:2:50:18 | call to operator delete | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:45:18:45:24 | new | new | +| test2.cpp:51:2:51:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:45:18:45:24 | new | new | +| test2.cpp:53:2:53:17 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:46:20:46:33 | call to operator new | malloc | +| test2.cpp:57:2:57:18 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:47:21:47:26 | call to malloc | malloc | | test.cpp:36:2:36:17 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:27:18:27:23 | call to malloc | malloc | | test.cpp:41:2:41:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:26:7:26:17 | new | new | | test.cpp:68:3:68:11 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:64:28:64:33 | call to malloc | malloc | diff --git a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp index 9101758d85b..15ab818d2c6 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp +++ b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp @@ -34,3 +34,27 @@ public: }; MyTest2Class mt2c_i; + +// --- + +void* operator new(size_t); +void operator delete(void*); + +void test_operator_new() +{ + void *ptr_new = new int; + void *ptr_opnew = ::operator new(sizeof(int)); + void *ptr_malloc = malloc(sizeof(int)); + + delete ptr_new; // GOOD + ::operator delete(ptr_new); // GOOD [FALSE POSITIVE] + free(ptr_new); // BAD + + delete ptr_opnew; // GOOD [FALSE POSITIVE] + ::operator delete(ptr_opnew); // GOOD + free(ptr_opnew); // BAD [NOT DETECTED] + + delete ptr_malloc; // BAD + ::operator delete(ptr_malloc); // BAD [NOT DETECTED] + free(ptr_malloc); // GOOD +} From 3e9f9645aecd8ad778ff9bcc97f098da0e7b985c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 11:30:14 +0100 Subject: [PATCH 321/459] C++: Exclude calls to operator new / delete from NewFreeMismatch.ql. --- cpp/ql/src/Critical/NewDelete.qll | 4 ++++ .../query-tests/Critical/NewFree/NewFreeMismatch.expected | 2 -- cpp/ql/test/query-tests/Critical/NewFree/test2.cpp | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index 9dd55525b59..7650af2f053 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -5,6 +5,8 @@ import cpp import semmle.code.cpp.controlflow.SSA import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.models.implementations.Allocation +import semmle.code.cpp.models.implementations.Deallocation /** * Holds if `alloc` is a use of `malloc` or `new`. `kind` is @@ -15,6 +17,7 @@ predicate allocExpr(Expr alloc, string kind) { not alloc.isFromUninstantiatedTemplate(_) and ( alloc instanceof FunctionCall and + not alloc.(FunctionCall).getTarget() instanceof OperatorNewAllocationFunction and kind = "malloc" or alloc instanceof NewExpr and @@ -111,6 +114,7 @@ predicate allocReaches(Expr e, Expr alloc, string kind) { */ predicate freeExpr(Expr free, Expr freed, string kind) { freeCall(free, freed) and + not free.(FunctionCall).getTarget() instanceof OperatorDeleteDeallocationFunction and kind = "free" or free.(DeleteExpr).getExpr() = freed and diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected index d588fc26e7b..8bcb9efa587 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected @@ -1,8 +1,6 @@ | test2.cpp:19:3:19:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:18:12:18:18 | new | new | | test2.cpp:26:3:26:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:25:7:25:13 | new | new | -| test2.cpp:50:2:50:18 | call to operator delete | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:45:18:45:24 | new | new | | test2.cpp:51:2:51:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:45:18:45:24 | new | new | -| test2.cpp:53:2:53:17 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:46:20:46:33 | call to operator new | malloc | | test2.cpp:57:2:57:18 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:47:21:47:26 | call to malloc | malloc | | test.cpp:36:2:36:17 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:27:18:27:23 | call to malloc | malloc | | test.cpp:41:2:41:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:26:7:26:17 | new | new | diff --git a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp index 15ab818d2c6..d5abd62ab71 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp +++ b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp @@ -47,10 +47,10 @@ void test_operator_new() void *ptr_malloc = malloc(sizeof(int)); delete ptr_new; // GOOD - ::operator delete(ptr_new); // GOOD [FALSE POSITIVE] + ::operator delete(ptr_new); // GOOD free(ptr_new); // BAD - delete ptr_opnew; // GOOD [FALSE POSITIVE] + delete ptr_opnew; // GOOD ::operator delete(ptr_opnew); // GOOD free(ptr_opnew); // BAD [NOT DETECTED] From 8059d69bbd754b7d26e93cfc109254e680e03b98 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 14:24:16 +0100 Subject: [PATCH 322/459] C++: Model calls to operator new / delete for NewFreeMismatch.ql. --- cpp/ql/src/Critical/NewDelete.qll | 33 +++++++++++++++---- .../Critical/NewFree/NewFreeMismatch.expected | 2 ++ .../query-tests/Critical/NewFree/test2.cpp | 4 +-- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index 7650af2f053..93d4ca0973c 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -16,9 +16,19 @@ predicate allocExpr(Expr alloc, string kind) { isAllocationExpr(alloc) and not alloc.isFromUninstantiatedTemplate(_) and ( - alloc instanceof FunctionCall and - not alloc.(FunctionCall).getTarget() instanceof OperatorNewAllocationFunction and - kind = "malloc" + exists(Function target | + alloc.(FunctionCall).getTarget() = target and + ( + target.getName() = "operator new" and + kind = "new" + or + target.getName() = "operator new[]" and + kind = "new[]" + or + not target instanceof OperatorNewAllocationFunction and + kind = "malloc" + ) + ) or alloc instanceof NewExpr and kind = "new" and @@ -113,9 +123,20 @@ predicate allocReaches(Expr e, Expr alloc, string kind) { * describing the type of that free or delete. */ predicate freeExpr(Expr free, Expr freed, string kind) { - freeCall(free, freed) and - not free.(FunctionCall).getTarget() instanceof OperatorDeleteDeallocationFunction and - kind = "free" + exists(Function target | + freeCall(free, freed) and + free.(FunctionCall).getTarget() = target and + ( + target.getName() = "operator delete" and + kind = "delete" + or + target.getName() = "operator delete[]" and + kind = "delete[]" + or + not target instanceof OperatorDeleteDeallocationFunction and + kind = "free" + ) + ) or free.(DeleteExpr).getExpr() = freed and kind = "delete" diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected index 8bcb9efa587..45f88d426c9 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected @@ -1,7 +1,9 @@ | test2.cpp:19:3:19:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:18:12:18:18 | new | new | | test2.cpp:26:3:26:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:25:7:25:13 | new | new | | test2.cpp:51:2:51:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:45:18:45:24 | new | new | +| test2.cpp:55:2:55:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:46:20:46:33 | call to operator new | new | | test2.cpp:57:2:57:18 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:47:21:47:26 | call to malloc | malloc | +| test2.cpp:58:2:58:18 | call to operator delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:47:21:47:26 | call to malloc | malloc | | test.cpp:36:2:36:17 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:27:18:27:23 | call to malloc | malloc | | test.cpp:41:2:41:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:26:7:26:17 | new | new | | test.cpp:68:3:68:11 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:64:28:64:33 | call to malloc | malloc | diff --git a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp index d5abd62ab71..43a286f6f97 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp +++ b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp @@ -52,9 +52,9 @@ void test_operator_new() delete ptr_opnew; // GOOD ::operator delete(ptr_opnew); // GOOD - free(ptr_opnew); // BAD [NOT DETECTED] + free(ptr_opnew); // BAD delete ptr_malloc; // BAD - ::operator delete(ptr_malloc); // BAD [NOT DETECTED] + ::operator delete(ptr_malloc); // BAD free(ptr_malloc); // GOOD } From e223557201d5326af4ee91c59a28815fc5694695 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 14:32:15 +0100 Subject: [PATCH 323/459] C++: Wean NewDelete.qll off the legacy wrapper Alloc.qll. --- cpp/ql/src/Critical/NewDelete.qll | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index 93d4ca0973c..1670dfc1357 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -13,8 +13,11 @@ import semmle.code.cpp.models.implementations.Deallocation * a string describing the type of the allocation. */ predicate allocExpr(Expr alloc, string kind) { - isAllocationExpr(alloc) and - not alloc.isFromUninstantiatedTemplate(_) and + ( + alloc.(FunctionCall) instanceof AllocationExpr + or + alloc = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer())) + ) and ( exists(Function target | alloc.(FunctionCall).getTarget() = target and @@ -41,7 +44,8 @@ predicate allocExpr(Expr alloc, string kind) { // exclude placement new and custom overloads as they // may not conform to assumptions not alloc.(NewArrayExpr).getAllocatorCall().getTarget().getNumberOfParameters() > 1 - ) + ) and + not alloc.isFromUninstantiatedTemplate(_) } /** @@ -124,7 +128,7 @@ predicate allocReaches(Expr e, Expr alloc, string kind) { */ predicate freeExpr(Expr free, Expr freed, string kind) { exists(Function target | - freeCall(free, freed) and + freed = free.(DeallocationExpr).getFreedExpr() and free.(FunctionCall).getTarget() = target and ( target.getName() = "operator delete" and From cbe133d0e6da1b8b1a6232818c84464307eda974 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 14:32:49 +0100 Subject: [PATCH 324/459] C++: Deprecate freeCall in the legacy wrapper Alloc.qll. --- cpp/ql/src/Critical/MemoryFreed.qll | 2 +- cpp/ql/src/semmle/code/cpp/commons/Alloc.qll | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Critical/MemoryFreed.qll b/cpp/ql/src/Critical/MemoryFreed.qll index d548aca26e7..880199e54c9 100644 --- a/cpp/ql/src/Critical/MemoryFreed.qll +++ b/cpp/ql/src/Critical/MemoryFreed.qll @@ -4,7 +4,7 @@ private predicate freed(Expr e) { e = any(DeallocationExpr de).getFreedExpr() or exists(ExprCall c | - // cautiously assume that any ExprCall could be a freeCall. + // cautiously assume that any `ExprCall` could be a deallocation expression. c.getAnArgument() = e ) } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll index a508c929d9a..a9597fc72b5 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll @@ -23,6 +23,8 @@ predicate freeFunction(Function f, int argNum) { argNum = f.(DeallocationFunctio /** * A call to a library routine that frees memory. + * + * DEPRECATED: Use `DeallocationExpr` instead (this also includes `delete` expressions). */ predicate freeCall(FunctionCall fc, Expr arg) { arg = fc.(DeallocationExpr).getFreedExpr() } From 050e2395072a38c9ab8834d6c360d6aa3331a780 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 14:37:47 +0100 Subject: [PATCH 325/459] C++: Change note. --- change-notes/1.24/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.24/analysis-cpp.md b/change-notes/1.24/analysis-cpp.md index 2b53e6d56aa..73d58a57404 100644 --- a/change-notes/1.24/analysis-cpp.md +++ b/change-notes/1.24/analysis-cpp.md @@ -53,3 +53,4 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. * The library now models data flow through formatting functions such as `sprintf`. * The security pack taint tracking library (`semmle.code.cpp.security.TaintTracking`) uses a new intermediate representation. This provides a more precise analysis of pointers to stack variables and flow through parameters, improving the results of many security queries. * The global value numbering library (`semmle.code.cpp.valuenumbering.GlobalValueNumbering`) uses a new intermediate representation to provide a more precise analysis of heap allocated memory and pointers to stack variables. +* `freeCall` in `semmle.code.cpp.commons.Alloc` has been deprecated. The`Allocation` and `Deallocation` models in `semmle.code.cpp.models.interfaces` should be used instead. From c5775418505de4e94753b63196106541f1ef49f0 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 6 Apr 2020 15:50:08 +0200 Subject: [PATCH 326/459] C++: Fix reverse read dataflow consistency failure and accept tests --- .../ir/dataflow/internal/DataFlowPrivate.qll | 6 ++--- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 22 +++++++++++++++++++ .../dataflow-ir-consistency.expected | 3 +++ .../dataflow-tests/test_diff.expected | 8 ++++--- .../dataflow/dataflow-tests/test_ir.expected | 8 +++---- .../dataflow/fields/ir-flow.expected | 21 ++++++++++++++++++ .../dataflow/taint-tests/test_diff.expected | 16 +++++--------- .../dataflow/taint-tests/test_ir.expected | 16 ++++---------- 8 files changed, 68 insertions(+), 32 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 5d99866e7ea..ddacf2dcb30 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -148,10 +148,10 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { */ predicate readStep(Node node1, Content f, Node node2) { exists(FieldAddressInstruction fa, LoadInstruction load | - fa.getField() = f.(FieldContent).getField() and - node1.asInstruction() = load and load.getSourceAddress() = fa and - node2.asInstruction().getAnOperand().getAnyDef() = load + node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and + fa.getField() = f.(FieldContent).getField() and + load = node2.asInstruction() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 49ff9a85ad5..88d221879fd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -257,9 +257,29 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { ) } + // There might be multiple `ChiInstructions` that has a particular instruction as + // the total operand - so this definition give consistency errors in + // DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications + // this consistency failure has. override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } } +private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode { + override StoreInstruction instr; + FieldAddressInstruction field; + + ExplicitSingleFieldStoreQualifierNode() { + field = instr.getDestinationAddress() and + not exists(ChiInstruction chi | chi.getPartial() = instr) + } + + // Since there is no Chi instruction with a total operand for us to use we let the pre update node + // be the address of the object containing the field. + // Note that, unlike in the case where a struct has multiple fields (and thus has a `Chi` + // instruction), the pre update node will be an instruction with a register result. + override Node getPreUpdateNode() { result.asInstruction() = field.getObjectAddress() } +} + /** * A node that represents the value of a variable after a function call that * may have changed the variable because it's passed by reference. @@ -281,6 +301,8 @@ class DefinitionByReferenceNode extends PartialDefinitionNode { call = write.getPrimaryInstruction() } + // See the comment on ExplicitFieldStoreQualifierNode::getPreUpdateNode for comments on why + // this causes failures in DataFlowImplConsistency::Consistency. override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } /** Gets the argument corresponding to this node. */ diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index 7abb7b4f4ae..99bf7799ff2 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -30,6 +30,9 @@ localCallNodes postIsNotPre postHasUniquePre uniquePostUpdate +| ref.cpp:83:5:83:17 | Chi | Node has multiple PostUpdateNodes. | +| ref.cpp:100:34:100:36 | InitializeIndirection | Node has multiple PostUpdateNodes. | +| ref.cpp:109:5:109:22 | Chi | Node has multiple PostUpdateNodes. | postIsInSameCallable reverseRead storeIsPostUpdate diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 8dae5a8dad8..11c5acc30fc 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -2,6 +2,7 @@ | BarrierGuard.cpp:60:11:60:16 | BarrierGuard.cpp:62:14:62:14 | AST only | | clang.cpp:12:9:12:20 | clang.cpp:22:8:22:20 | AST only | | clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only | +| clang.cpp:28:27:28:32 | clang.cpp:31:27:31:28 | IR only | | clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only | @@ -31,6 +32,10 @@ | ref.cpp:53:17:53:18 | ref.cpp:62:10:62:11 | AST only | | ref.cpp:53:21:53:22 | ref.cpp:65:10:65:11 | AST only | | ref.cpp:55:23:55:28 | ref.cpp:56:10:56:11 | AST only | +| ref.cpp:94:15:94:20 | ref.cpp:129:13:129:15 | AST only | +| ref.cpp:109:15:109:20 | ref.cpp:132:13:132:15 | AST only | +| ref.cpp:122:23:122:28 | ref.cpp:123:13:123:15 | AST only | +| ref.cpp:125:19:125:24 | ref.cpp:126:13:126:15 | AST only | | test.cpp:75:7:75:8 | test.cpp:76:8:76:9 | AST only | | test.cpp:83:7:83:8 | test.cpp:84:8:84:18 | AST only | | test.cpp:83:7:83:8 | test.cpp:86:8:86:9 | AST only | @@ -41,9 +46,6 @@ | test.cpp:359:13:359:18 | test.cpp:365:10:365:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:369:10:369:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:375:10:375:14 | AST only | -| test.cpp:382:48:382:54 | test.cpp:385:8:385:10 | AST only | -| test.cpp:388:53:388:59 | test.cpp:392:8:392:10 | AST only | -| test.cpp:388:53:388:59 | test.cpp:394:10:394:12 | AST only | | test.cpp:399:7:399:9 | test.cpp:401:8:401:10 | AST only | | test.cpp:405:7:405:9 | test.cpp:408:8:408:10 | AST only | | test.cpp:416:7:416:11 | test.cpp:418:8:418:12 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 202d9827323..f4e072d1905 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -12,6 +12,7 @@ | clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 | | clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 | | clang.cpp:29:27:29:28 | m1 | clang.cpp:28:27:28:32 | call to source | +| clang.cpp:31:27:31:28 | m2 | clang.cpp:28:27:28:32 | call to source | | clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source | | clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source | | clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source | @@ -39,10 +40,6 @@ | globals.cpp:12:10:12:24 | flowTestGlobal1 | globals.cpp:13:23:13:28 | call to source | | globals.cpp:19:10:19:24 | flowTestGlobal2 | globals.cpp:23:23:23:28 | call to source | | lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source | -| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source | -| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source | -| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source | -| ref.cpp:132:13:132:15 | val | ref.cpp:109:15:109:20 | call to source | | test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source | @@ -65,6 +62,9 @@ | test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source | | test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source | | test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source | +| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 | +| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 | +| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 | | test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 | | test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 | | true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index 2503be80b00..ad56e8af8a7 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -1,24 +1,45 @@ edges +| aliasing.cpp:37:3:37:24 | Store : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | Store : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | Store : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | Store : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:86:3:86:21 | Store : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | Store : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:92:3:92:23 | Store : void | aliasing.cpp:93:12:93:13 | m1 | +| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | Store : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | +| struct_init.c:20:20:20:29 | Store : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | Store : void | | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | +| struct_init.c:27:7:27:16 | Store : void | struct_init.c:31:23:31:23 | a | +| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | Store : void | | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | nodes +| aliasing.cpp:37:3:37:24 | Store : void | semmle.label | Store : void | | aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | +| aliasing.cpp:42:3:42:22 | Store : void | semmle.label | Store : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | +| aliasing.cpp:79:3:79:22 | Store : void | semmle.label | Store : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | +| aliasing.cpp:86:3:86:21 | Store : void | semmle.label | Store : void | | aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | +| aliasing.cpp:92:3:92:23 | Store : void | semmle.label | Store : void | | aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | +| struct_init.c:20:20:20:29 | Store : void | semmle.label | Store : void | | struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void | | struct_init.c:22:11:22:11 | a | semmle.label | a | +| struct_init.c:27:7:27:16 | Store : void | semmle.label | Store : void | | struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void | | struct_init.c:31:23:31:23 | a | semmle.label | a | #select 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 9789a2bda21..ffe098d6063 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 @@ -11,25 +11,21 @@ | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | -| taint.cpp:88:11:88:11 | taint.cpp:77:7:77:12 | IR only | | taint.cpp:89:11:89:11 | taint.cpp:71:22:71:27 | AST only | -| taint.cpp:89:11:89:11 | taint.cpp:77:7:77:12 | IR only | | taint.cpp:90:11:90:11 | taint.cpp:72:7:72:12 | AST only | -| taint.cpp:90:11:90:11 | taint.cpp:77:7:77:12 | IR only | -| taint.cpp:92:11:92:11 | taint.cpp:71:22:71:27 | IR only | -| taint.cpp:92:11:92:11 | taint.cpp:72:7:72:12 | IR only | -| taint.cpp:93:11:93:11 | taint.cpp:72:7:72:12 | IR only | -| taint.cpp:94:11:94:11 | taint.cpp:71:22:71:27 | IR only | -| taint.cpp:95:11:95:11 | taint.cpp:71:22:71:27 | IR only | -| taint.cpp:95:11:95:11 | taint.cpp:72:7:72:12 | IR only | +| taint.cpp:91:11:91:11 | taint.cpp:77:7:77:12 | AST only | +| taint.cpp:93:11:93:11 | taint.cpp:71:22:71:27 | AST only | +| taint.cpp:94:11:94:11 | taint.cpp:72:7:72:12 | AST only | | taint.cpp:109:7:109:13 | taint.cpp:105:12:105:17 | IR only | +| taint.cpp:110:7:110:13 | taint.cpp:105:12:105:17 | IR only | +| taint.cpp:111:7:111:13 | taint.cpp:106:12:106:17 | IR only | +| taint.cpp:112:7:112:13 | taint.cpp:106:12:106:17 | IR only | | taint.cpp:130:7:130:9 | taint.cpp:127:8:127:13 | IR only | | taint.cpp:137:7:137:9 | taint.cpp:120:11:120:16 | AST only | | taint.cpp:173:8:173:13 | taint.cpp:164:19:164:24 | AST only | | taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only | -| taint.cpp:216:7:216:7 | taint.cpp:207:6:207:11 | AST only | | taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | 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 751775e21ab..e6f138e6283 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,19 +1,10 @@ | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | -| taint.cpp:88:11:88:11 | a | taint.cpp:77:7:77:12 | call to source | -| taint.cpp:89:11:89:11 | b | taint.cpp:77:7:77:12 | call to source | -| taint.cpp:90:11:90:11 | c | taint.cpp:77:7:77:12 | call to source | -| taint.cpp:91:11:91:11 | d | taint.cpp:77:7:77:12 | call to source | -| taint.cpp:92:11:92:11 | a | taint.cpp:71:22:71:27 | call to source | -| taint.cpp:92:11:92:11 | a | taint.cpp:72:7:72:12 | call to source | -| taint.cpp:93:11:93:11 | b | taint.cpp:71:22:71:27 | call to source | -| taint.cpp:93:11:93:11 | b | taint.cpp:72:7:72:12 | call to source | -| taint.cpp:94:11:94:11 | c | taint.cpp:71:22:71:27 | call to source | -| taint.cpp:94:11:94:11 | c | taint.cpp:72:7:72:12 | call to source | -| taint.cpp:95:11:95:11 | d | taint.cpp:71:22:71:27 | call to source | -| taint.cpp:95:11:95:11 | d | taint.cpp:72:7:72:12 | call to source | | taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source | +| taint.cpp:110:7:110:13 | access to array | taint.cpp:105:12:105:17 | call to source | +| taint.cpp:111:7:111:13 | access to array | taint.cpp:106:12:106:17 | call to source | +| taint.cpp:112:7:112:13 | access to array | taint.cpp:106:12:106:17 | call to source | | taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source | | taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source | | taint.cpp:134:7:134:9 | * ... | taint.cpp:120:11:120:16 | call to source | @@ -22,6 +13,7 @@ | taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source | | taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source | +| taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source | | taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source | | taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source | | taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source | From 492c5f367f7f4c4fe142c9e6d79040df0738ffbe Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 14:44:38 +0100 Subject: [PATCH 327/459] C++: Simplify NewDelete.qll. --- cpp/ql/src/Critical/NewDelete.qll | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index 1670dfc1357..b9c84c04a3a 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -13,14 +13,9 @@ import semmle.code.cpp.models.implementations.Deallocation * a string describing the type of the allocation. */ predicate allocExpr(Expr alloc, string kind) { - ( - alloc.(FunctionCall) instanceof AllocationExpr - or - alloc = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer())) - ) and ( exists(Function target | - alloc.(FunctionCall).getTarget() = target and + alloc.(AllocationExpr).(FunctionCall).getTarget() = target and ( target.getName() = "operator new" and kind = "new" From a71ae2b4687d60818f041a3aa1e5bd240b2d2f30 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 14:46:00 +0100 Subject: [PATCH 328/459] C++: Consistent treatment of placement new. --- cpp/ql/src/Critical/NewDelete.qll | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index b9c84c04a3a..30b9f9ad94a 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -18,10 +18,16 @@ predicate allocExpr(Expr alloc, string kind) { alloc.(AllocationExpr).(FunctionCall).getTarget() = target and ( target.getName() = "operator new" and - kind = "new" + kind = "new" and + // exclude placement new and custom overloads as they + // may not conform to assumptions + not target.getNumberOfParameters() > 1 or target.getName() = "operator new[]" and - kind = "new[]" + kind = "new[]" and + // exclude placement new and custom overloads as they + // may not conform to assumptions + not target.getNumberOfParameters() > 1 or not target instanceof OperatorNewAllocationFunction and kind = "malloc" From d5accc70e13dbea1a43e4d39301472aeffb68155 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 6 Apr 2020 16:47:24 +0100 Subject: [PATCH 329/459] C++: Add a test similar to issues/44. --- .../dataflow/taint-tests/localTaint.expected | 10 +++++++++ .../dataflow/taint-tests/stl.cpp | 21 +++++++++++++++++++ .../dataflow/taint-tests/taint.expected | 3 +++ .../dataflow/taint-tests/test_diff.expected | 3 +++ 4 files changed, 37 insertions(+) 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 72433bccfb4..ec88e5bc628 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -152,6 +152,16 @@ | stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:110:7:110:9 | ss1 | | | stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:109:7:109:9 | ss2 | | | stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:111:7:111:9 | ss2 | | +| stl.cpp:124:16:124:28 | call to basic_string | stl.cpp:125:7:125:11 | path1 | | +| stl.cpp:124:17:124:26 | call to user_input | stl.cpp:124:16:124:28 | call to basic_string | TAINT | +| stl.cpp:125:7:125:11 | path1 | stl.cpp:125:13:125:17 | call to c_str | TAINT | +| stl.cpp:128:10:128:19 | call to user_input | stl.cpp:128:10:128:21 | call to basic_string | TAINT | +| stl.cpp:128:10:128:21 | call to basic_string | stl.cpp:128:2:128:21 | ... = ... | | +| stl.cpp:128:10:128:21 | call to basic_string | stl.cpp:129:7:129:11 | path2 | | +| stl.cpp:129:7:129:11 | path2 | stl.cpp:129:13:129:17 | call to c_str | TAINT | +| stl.cpp:131:15:131:24 | call to user_input | stl.cpp:131:15:131:27 | call to basic_string | TAINT | +| stl.cpp:131:15:131:27 | call to basic_string | stl.cpp:132:7:132:11 | path3 | | +| stl.cpp:132:7:132:11 | path3 | stl.cpp:132:13:132:17 | call to c_str | TAINT | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 54755871f6a..d92bb39d158 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -110,3 +110,24 @@ void test_stringstream_int(int source) 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 +} 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 f8365ae63c7..59193d81722 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -11,6 +11,9 @@ | stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | | stl.cpp:73:7:73:7 | c | stl.cpp:69:16:69:21 | call to source | | stl.cpp:75:9:75:13 | call to c_str | stl.cpp:69:16:69:21 | call to source | +| stl.cpp:125:13:125:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | +| stl.cpp:129:13:129:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | +| stl.cpp:132:13:132:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | 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 7457b361f39..af9d002dcdc 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 @@ -10,6 +10,9 @@ | format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | AST only | | stl.cpp:73:7:73:7 | stl.cpp:69:16:69:21 | AST only | | stl.cpp:75:9:75:13 | stl.cpp:69:16:69:21 | AST only | +| stl.cpp:125:13:125:17 | stl.cpp:117:10:117:15 | AST only | +| stl.cpp:129:13:129:17 | stl.cpp:117:10:117:15 | AST only | +| stl.cpp:132:13:132:17 | stl.cpp:117:10:117:15 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | From bf579dedd4d841270f9c82a0bea9dd4acd5b367d Mon Sep 17 00:00:00 2001 From: Henning Makholm Date: Wed, 1 Apr 2020 04:04:29 +0200 Subject: [PATCH 330/459] Add extractor field in base language QL packs --- cpp/ql/src/qlpack.yml | 1 + csharp/ql/src/qlpack.yml | 1 + java/ql/src/qlpack.yml | 1 + javascript/ql/src/qlpack.yml | 1 + python/ql/src/qlpack.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index a1c7df902de..45ae614f88e 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-cpp version: 0.0.0 dbscheme: semmlecode.cpp.dbscheme suites: codeql-suites +extractor: cpp diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index df14eec51a7..6bb4774c070 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-csharp version: 0.0.0 dbscheme: semmlecode.csharp.dbscheme suites: codeql-suites +extractor: csharp diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index f8b703f9440..7c48700e295 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-java version: 0.0.0 dbscheme: config/semmlecode.dbscheme suites: codeql-suites +extractor: java diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 1f587affc85..7612a1d52f2 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-javascript version: 0.0.0 dbscheme: semmlecode.javascript.dbscheme suites: codeql-suites +extractor: javascript diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 23027b6d95e..9807b169d44 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-python version: 0.0.0 dbscheme: semmlecode.python.dbscheme suites: codeql-suites +extractor: python From d1ff3211ef222164b55b5fe49ec4fdc6e39237bb Mon Sep 17 00:00:00 2001 From: Henning Makholm Date: Mon, 6 Apr 2020 19:20:31 +0200 Subject: [PATCH 331/459] Add extractor fields to test qlpack.yml files. --- cpp/ql/test/qlpack.yml | 1 + csharp/ql/test/qlpack.yml | 1 + java/ql/test/qlpack.yml | 1 + javascript/ql/test/qlpack.yml | 1 + python/ql/test/qlpack.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/cpp/ql/test/qlpack.yml b/cpp/ql/test/qlpack.yml index 36dcb70d4ef..008af57baef 100644 --- a/cpp/ql/test/qlpack.yml +++ b/cpp/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-cpp-tests version: 0.0.0 libraryPathDependencies: codeql-cpp +extractor: cpp diff --git a/csharp/ql/test/qlpack.yml b/csharp/ql/test/qlpack.yml index 20f6e83ee30..2b8cce91f07 100644 --- a/csharp/ql/test/qlpack.yml +++ b/csharp/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-csharp-tests version: 0.0.0 libraryPathDependencies: codeql-csharp +extractor: csharp diff --git a/java/ql/test/qlpack.yml b/java/ql/test/qlpack.yml index d4b46d7d2b0..75a27d69080 100644 --- a/java/ql/test/qlpack.yml +++ b/java/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-java-tests version: 0.0.0 libraryPathDependencies: codeql-java +extractor: java diff --git a/javascript/ql/test/qlpack.yml b/javascript/ql/test/qlpack.yml index d40472ed653..76f050e0b81 100644 --- a/javascript/ql/test/qlpack.yml +++ b/javascript/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-javascript-tests version: 0.0.0 libraryPathDependencies: codeql-javascript +extractor: javascript diff --git a/python/ql/test/qlpack.yml b/python/ql/test/qlpack.yml index eed82a82aec..afae7523793 100644 --- a/python/ql/test/qlpack.yml +++ b/python/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-python-tests version: 0.0.0 libraryPathDependencies: codeql-python +extractor: python From 1077ce3a35086a3b1463505691edfebf26c2b584 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 7 Apr 2020 09:26:14 +0200 Subject: [PATCH 332/459] Python: Add FN for py/unused-import --- .../test/query-tests/Imports/unused/UnusedImport.expected | 1 + .../test/query-tests/Imports/unused/import_structure_1.py | 8 ++++++++ .../test/query-tests/Imports/unused/import_structure_2.py | 8 ++++++++ 3 files changed, 17 insertions(+) create mode 100644 python/ql/test/query-tests/Imports/unused/import_structure_1.py create mode 100644 python/ql/test/query-tests/Imports/unused/import_structure_2.py diff --git a/python/ql/test/query-tests/Imports/unused/UnusedImport.expected b/python/ql/test/query-tests/Imports/unused/UnusedImport.expected index 163bcab7b3d..95e91ded7ad 100644 --- a/python/ql/test/query-tests/Imports/unused/UnusedImport.expected +++ b/python/ql/test/query-tests/Imports/unused/UnusedImport.expected @@ -1,3 +1,4 @@ +| import_structure_2.py:6:1:6:23 | Import | Import of 'bar' is not used. | | imports_test.py:2:1:2:23 | Import | Import of 'module2' is not used. | | imports_test.py:6:1:6:12 | Import | Import of 'cycle' is not used. | | imports_test.py:10:1:10:22 | Import | Import of 'top_level_cycle' is not used. | diff --git a/python/ql/test/query-tests/Imports/unused/import_structure_1.py b/python/ql/test/query-tests/Imports/unused/import_structure_1.py new file mode 100644 index 00000000000..a76fe99f12c --- /dev/null +++ b/python/ql/test/query-tests/Imports/unused/import_structure_1.py @@ -0,0 +1,8 @@ +# there should be no difference whether you import 2 things on 1 line, or use 2 +# lines +from typing import Optional + +from unknown import foo, bar + + +var: Optional['foo'] = None diff --git a/python/ql/test/query-tests/Imports/unused/import_structure_2.py b/python/ql/test/query-tests/Imports/unused/import_structure_2.py new file mode 100644 index 00000000000..90d4255ba39 --- /dev/null +++ b/python/ql/test/query-tests/Imports/unused/import_structure_2.py @@ -0,0 +1,8 @@ +# there should be no difference whether you import 2 things on 1 line, or use 2 +# lines +from typing import Optional + +from unknown import foo +from unknown import bar + +var: Optional['foo'] = None From 75e6470009f21ed7f4b92323204dd42d001ea89c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 7 Apr 2020 09:41:42 +0200 Subject: [PATCH 333/459] Python: Fix FN in py/unused-import --- python/ql/src/Imports/UnusedImport.ql | 20 ++++++++++--------- .../Imports/unused/UnusedImport.expected | 1 + 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index ac93d9886f1..b8e4903b743 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -62,7 +62,7 @@ private string doctest_in_scope(Scope scope) { } pragma[noinline] -private string typehint_annotation_in_file(File file) { +private string typehint_annotation_in_module(Module module_scope) { exists(StrConst annotation | annotation = any(Arguments a).getAnAnnotation().getASubExpression*() or @@ -71,7 +71,7 @@ private string typehint_annotation_in_file(File file) { annotation = any(FunctionExpr f).getReturns().getASubExpression*() | annotation.pointsTo(Value::forString(result)) and - file = annotation.getLocation().getFile() + annotation.getEnclosingModule() = module_scope ) } @@ -84,17 +84,19 @@ private string typehint_comment_in_file(File file) { ) } -predicate imported_module_used_in_typehint(Import imp) { - exists(string modname, File file | - imp.getAName().getAsname().(Name).getId() = modname and - file = imp.getScope().(Module).getFile() +/** Holds if the imported alias `name` from `imp` is used in a typehint (in the same file as `imp`) */ +predicate imported_alias_used_in_typehint(Import imp, Variable name) { + imp.getAName().getAsname().(Name).getVariable() = name and + exists(File file, Module module_scope | + module_scope = imp.getEnclosingModule() and + file = module_scope.getFile() | // Look for type hints containing the patterns: // # type: …name… - typehint_comment_in_file(file).regexpMatch("# type:.*" + modname + ".*") + typehint_comment_in_file(file).regexpMatch("# type:.*" + name.getId() + ".*") or // Type hint is inside a string annotation, as needed for forward references - typehint_annotation_in_file(file).regexpMatch(".*\\b" + modname + "\\b.*") + typehint_annotation_in_module(module_scope).regexpMatch(".*\\b" + name.getId() + "\\b.*") ) } @@ -114,7 +116,7 @@ predicate unused_import(Import imp, Variable name) { // Assume that opaque `__all__` includes imported module not all_not_understood(imp.getEnclosingModule()) and not imported_module_used_in_doctest(imp) and - not imported_module_used_in_typehint(imp) and + not imported_alias_used_in_typehint(imp, name) and // Only consider import statements that actually point-to something (possibly an unknown module). // If this is not the case, it's likely that the import statement never gets executed. imp.getAName().getValue().pointsTo(_) diff --git a/python/ql/test/query-tests/Imports/unused/UnusedImport.expected b/python/ql/test/query-tests/Imports/unused/UnusedImport.expected index 95e91ded7ad..47bedf61d7c 100644 --- a/python/ql/test/query-tests/Imports/unused/UnusedImport.expected +++ b/python/ql/test/query-tests/Imports/unused/UnusedImport.expected @@ -1,3 +1,4 @@ +| import_structure_1.py:5:1:5:28 | Import | Import of 'bar' is not used. | | import_structure_2.py:6:1:6:23 | Import | Import of 'bar' is not used. | | imports_test.py:2:1:2:23 | Import | Import of 'module2' is not used. | | imports_test.py:6:1:6:12 | Import | Import of 'cycle' is not used. | From 5719967a8ed77088a94fbbec567819ba19ab348f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 7 Apr 2020 12:03:28 +0200 Subject: [PATCH 334/459] C++: Remove single-field case from PostUpdateNode and accept tests --- .../ir/dataflow/internal/DataFlowPrivate.qll | 10 ++-- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 52 +++++++------------ .../dataflow-ir-consistency.expected | 1 - .../dataflow/fields/ir-flow.expected | 10 ++++ .../CWE-134/semmle/funcs/funcsLocal.expected | 1 + 5 files changed, 33 insertions(+), 41 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index ddacf2dcb30..f81be05c66b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -131,12 +131,10 @@ private class ArrayContent extends Content, TArrayContent { * value of `node1`. */ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { - exists(FieldAddressInstruction fa | - exists(StoreInstruction store | - node1.asInstruction() = store and - store.getDestinationAddress() = fa - ) and - node2.getPreUpdateNode().asInstruction() = fa.getObjectAddress() and + exists(FieldAddressInstruction fa, StoreInstruction store | + node1.asInstruction() = store and + store.getDestinationAddress() = fa and + node2.asInstruction().(ChiInstruction).getPartial() = store and f.(FieldContent).getField() = fa.getField() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 88d221879fd..a7a5f9d6d86 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -264,22 +264,6 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } } -private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode { - override StoreInstruction instr; - FieldAddressInstruction field; - - ExplicitSingleFieldStoreQualifierNode() { - field = instr.getDestinationAddress() and - not exists(ChiInstruction chi | chi.getPartial() = instr) - } - - // Since there is no Chi instruction with a total operand for us to use we let the pre update node - // be the address of the object containing the field. - // Note that, unlike in the case where a struct has multiple fields (and thus has a `Chi` - // instruction), the pre update node will be an instruction with a register result. - override Node getPreUpdateNode() { result.asInstruction() = field.getObjectAddress() } -} - /** * A node that represents the value of a variable after a function call that * may have changed the variable because it's passed by reference. @@ -290,31 +274,31 @@ private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNod * returned. This node will have its `getArgument()` equal to `&x` and its * `getVariableAccess()` equal to `x`. */ -class DefinitionByReferenceNode extends PartialDefinitionNode { - override ChiInstruction instr; - WriteSideEffectInstruction write; - CallInstruction call; - - DefinitionByReferenceNode() { - not instr.isResultConflated() and - instr.getPartial() = write and - call = write.getPrimaryInstruction() - } - - // See the comment on ExplicitFieldStoreQualifierNode::getPreUpdateNode for comments on why - // this causes failures in DataFlowImplConsistency::Consistency. - override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } +class DefinitionByReferenceNode extends InstructionNode { + override WriteSideEffectInstruction instr; /** Gets the argument corresponding to this node. */ Expr getArgument() { - result = call.getPositionalArgument(write.getIndex()).getUnconvertedResultExpression() + result = + instr + .getPrimaryInstruction() + .(CallInstruction) + .getPositionalArgument(instr.getIndex()) + .getUnconvertedResultExpression() or - result = call.getThisArgument().getUnconvertedResultExpression() and - write.getIndex() = -1 + result = + instr + .getPrimaryInstruction() + .(CallInstruction) + .getThisArgument() + .getUnconvertedResultExpression() and + instr.getIndex() = -1 } /** Gets the parameter through which this value is assigned. */ - Parameter getParameter() { result = call.getStaticCallTarget().getParameter(write.getIndex()) } + Parameter getParameter() { + exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex())) + } } /** diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index 99bf7799ff2..3940c1e8389 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -31,7 +31,6 @@ postIsNotPre postHasUniquePre uniquePostUpdate | ref.cpp:83:5:83:17 | Chi | Node has multiple PostUpdateNodes. | -| ref.cpp:100:34:100:36 | InitializeIndirection | Node has multiple PostUpdateNodes. | | ref.cpp:109:5:109:22 | Chi | Node has multiple PostUpdateNodes. | postIsInSameCallable reverseRead diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index ad56e8af8a7..6d34e81e849 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -5,6 +5,10 @@ edges | aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:43:13:43:14 | m1 | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | Store : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:60:3:60:22 | Chi [m1] : void | aliasing.cpp:61:13:61:14 | Store [m1] : void | +| aliasing.cpp:60:3:60:22 | Store : void | aliasing.cpp:60:3:60:22 | Chi [m1] : void | +| aliasing.cpp:60:11:60:20 | call to user_input : void | aliasing.cpp:60:3:60:22 | Store : void | +| aliasing.cpp:61:13:61:14 | Store [m1] : void | aliasing.cpp:62:14:62:15 | m1 | | aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:80:12:80:13 | m1 | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | Store : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | @@ -27,6 +31,11 @@ nodes | aliasing.cpp:42:3:42:22 | Store : void | semmle.label | Store : void | | aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | +| aliasing.cpp:60:3:60:22 | Chi [m1] : void | semmle.label | Chi [m1] : void | +| aliasing.cpp:60:3:60:22 | Store : void | semmle.label | Store : void | +| aliasing.cpp:60:11:60:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:61:13:61:14 | Store [m1] : void | semmle.label | Store [m1] : void | +| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 | | aliasing.cpp:79:3:79:22 | Store : void | semmle.label | Store : void | | aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | @@ -45,6 +54,7 @@ nodes #select | aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void | | aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input : void | call to user_input : void | +| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input : void | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input : void | call to user_input : void | | aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input : void | call to user_input : void | | aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input : void | call to user_input : void | | aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input : void | call to user_input : void | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 2417990beb2..5ae6a003bed 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -5,3 +5,4 @@ | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets | | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets | +| funcsLocal.c:58:9:58:10 | e1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | From 39eb1a38258011fe96118b6b1ef4789e50454e00 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Tue, 11 Feb 2020 19:34:56 +0000 Subject: [PATCH 335/459] C#: Remove assembly qualifier from some trap-ids. --- .../Semmle.Extraction.CSharp/Entities/Method.cs | 5 +---- .../Semmle.Extraction.CSharp/Entities/Types/NamedType.cs | 8 ++++++-- .../Semmle.Extraction.CSharp/Entities/Types/TupleType.cs | 2 +- .../Semmle.Extraction.CSharp/SymbolExtensions.cs | 9 ++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 999903a1da8..21538a57741 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -201,10 +201,7 @@ namespace Semmle.Extraction.CSharp.Entities /// protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type) { - if (type.ContainsTypeParameters(cx, method)) - type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0)); - else - trapFile.WriteSubId(Type.Create(cx, type)); + type.BuildTypeId(cx, trapFile, false, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0)); } protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index cecec5bc028..4e584180c7c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -111,7 +111,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, true, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";type"); } @@ -177,7 +177,11 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(referencedType); + void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol) + { + symbol.BuildTypeId(cx, trapFile, false, WriteType); + } + WriteType(Context, trapFile, referencedType.symbol); trapFile.Write(";typeRef"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index de6ea217084..e0adee16142 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, false, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";tuple"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 6050ad910a5..c871da6e59a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -131,9 +131,9 @@ namespace Semmle.Extraction.CSharp /// The extraction context. /// The trap builder used to store the result. /// The action to apply to syntactic sub terms of this type. - public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction) + public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, Action subTermAction) { - if (type.SpecialType != SpecialType.None) + if (type.SpecialType != SpecialType.None && !(type is INamedTypeSymbol n && n.IsGenericType)) { /* * Use the keyword ("int" etc) for the built-in types. @@ -160,7 +160,7 @@ namespace Semmle.Extraction.CSharp case TypeKind.Delegate: case TypeKind.Error: var named = (INamedTypeSymbol)type; - named.BuildNamedTypeId(cx, trapFile, subTermAction); + named.BuildNamedTypeId(cx, trapFile, prefix, subTermAction); return; case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; @@ -211,9 +211,8 @@ namespace Semmle.Extraction.CSharp trapFile.Write("::"); } - static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) + static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, bool prefixAssembly, Action subTermAction) { - bool prefixAssembly = true; if (named.ContainingAssembly is null) prefixAssembly = false; if (named.IsTupleType) From 9ec0c8f3ec1a0b5df05fdfcc54ead9876572ff88 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Wed, 12 Feb 2020 13:52:17 +0000 Subject: [PATCH 336/459] C#: Qualify type parameters with the entity that declares them --- .../Entities/Constructor.cs | 2 +- .../Entities/Method.cs | 14 +++---- .../Entities/Types/NamedType.cs | 8 ++-- .../Entities/Types/TupleType.cs | 2 +- .../Entities/UserOperator.cs | 2 +- .../SymbolExtensions.cs | 41 +++++++++++++------ 6 files changed, 42 insertions(+), 27 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs index 298f838cfb9..3230ad699f6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs @@ -114,7 +114,7 @@ namespace Semmle.Extraction.CSharp.Entities { if (symbol.IsStatic) trapFile.Write("static"); trapFile.WriteSubId(ContainingType); - AddParametersToId(Context, trapFile, symbol); + AddParametersToId(Context, trapFile, symbol, symbol); trapFile.Write(";constructor"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 21538a57741..77c9e2ab21d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -129,12 +129,12 @@ namespace Semmle.Extraction.CSharp.Entities // 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); }); + trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol, m.symbol); trapFile.Write((int)ta.Nullability); }); trapFile.Write('>'); } } - AddParametersToId(m.Context, trapFile, m.symbol); + AddParametersToId(m.Context, trapFile, m.symbol, m.symbol); switch (m.symbol.MethodKind) { case MethodKind.PropertyGet: @@ -199,12 +199,12 @@ namespace Semmle.Extraction.CSharp.Entities /// to make the reference to #3 in the label definition #4 for /// T valid. /// - protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type) + protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type, ISymbol symbolBeingDefined) { - type.BuildTypeId(cx, trapFile, false, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0)); + type.BuildTypeId(cx, trapFile, false, symbolBeingDefined, (cx0, tb0, type0, g) => AddSignatureTypeToId(cx, tb0, method, type0, g)); } - protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method) + protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method, ISymbol generic) { trapFile.Write('('); int index = 0; @@ -212,13 +212,13 @@ namespace Semmle.Extraction.CSharp.Entities if (method.MethodKind == MethodKind.ReducedExtension) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType); + AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, generic); } foreach (var param in method.Parameters) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, param.Type); + AddSignatureTypeToId(cx, trapFile, method, param.Type, generic); switch (param.RefKind) { case RefKind.Out: diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 4e584180c7c..5611477daf0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -111,7 +111,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, true, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, g) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";type"); } @@ -177,11 +177,11 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol) + void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol, ISymbol symbolBeingDefined) { - symbol.BuildTypeId(cx, trapFile, false, WriteType); + symbol.BuildTypeId(cx, trapFile, false, symbolBeingDefined, WriteType); } - WriteType(Context, trapFile, referencedType.symbol); + WriteType(Context, trapFile, referencedType.symbol, referencedType.symbol); trapFile.Write(";typeRef"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index e0adee16142..4f5e5f68d40 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, false, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, g) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";tuple"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs index 2a64a29fa0d..9c94058af1f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs @@ -51,7 +51,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType); // Needed for op_explicit(), which differs only by return type. + AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType, symbol); // Needed for op_explicit(), which differs only by return type. trapFile.Write(' '); BuildMethodId(this, trapFile); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index c871da6e59a..7acfc502720 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -131,7 +131,7 @@ namespace Semmle.Extraction.CSharp /// The extraction context. /// The trap builder used to store the result. /// The action to apply to syntactic sub terms of this type. - public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, Action subTermAction) + public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, ISymbol SymbolBeingDefined, Action subTermAction) { if (type.SpecialType != SpecialType.None && !(type is INamedTypeSymbol n && n.IsGenericType)) { @@ -150,7 +150,7 @@ namespace Semmle.Extraction.CSharp { case TypeKind.Array: var array = (IArrayTypeSymbol)type; - subTermAction(cx, trapFile, array.ElementType); + subTermAction(cx, trapFile, array.ElementType, SymbolBeingDefined); array.BuildArraySuffix(trapFile); return; case TypeKind.Class: @@ -160,15 +160,30 @@ namespace Semmle.Extraction.CSharp case TypeKind.Delegate: case TypeKind.Error: var named = (INamedTypeSymbol)type; - named.BuildNamedTypeId(cx, trapFile, prefix, subTermAction); + named.BuildNamedTypeId(cx, trapFile, prefix, SymbolBeingDefined, subTermAction); return; case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; - subTermAction(cx, trapFile, ptr.PointedAtType); + subTermAction(cx, trapFile, ptr.PointedAtType, SymbolBeingDefined); trapFile.Write('*'); return; case TypeKind.TypeParameter: var tp = (ITypeParameterSymbol)type; + if (!SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, SymbolBeingDefined)) + { + switch (tp.TypeParameterKind) + { + case TypeParameterKind.Method: + var method = Method.Create(cx, (IMethodSymbol)tp.ContainingSymbol); + trapFile.WriteSubId(method); + trapFile.Write('_'); + break; + case TypeParameterKind.Type: + subTermAction(cx, trapFile, tp.ContainingType, SymbolBeingDefined); + trapFile.Write('_'); + break; + } + } trapFile.Write(tp.Name); return; case TypeKind.Dynamic: @@ -211,7 +226,7 @@ namespace Semmle.Extraction.CSharp trapFile.Write("::"); } - static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, bool prefixAssembly, Action subTermAction) + static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, bool prefixAssembly, ISymbol symbolBeingDefined, Action subTermAction) { if (named.ContainingAssembly is null) prefixAssembly = false; @@ -223,7 +238,7 @@ namespace Semmle.Extraction.CSharp { trapFile.Write(f.Name); trapFile.Write(":"); - subTermAction(cx, tb0, f.Type); + subTermAction(cx, tb0, f.Type, symbolBeingDefined); } ); trapFile.Write(")"); @@ -232,7 +247,7 @@ namespace Semmle.Extraction.CSharp if (named.ContainingType != null) { - subTermAction(cx, trapFile, named.ContainingType); + subTermAction(cx, trapFile, named.ContainingType, symbolBeingDefined); trapFile.Write('.'); } else if (named.ContainingNamespace != null) @@ -254,14 +269,14 @@ namespace Semmle.Extraction.CSharp } else { - subTermAction(cx, trapFile, named.ConstructedFrom); + subTermAction(cx, trapFile, named.ConstructedFrom, symbolBeingDefined); trapFile.Write('<'); // Encode the nullability of the type arguments in the label. // Type arguments with different nullability can result in // a constructed type with different nullability of its members and methods, // so we need to create a distinct database entity for it. trapFile.BuildList(",", named.GetAnnotatedTypeArguments(), - (ta, tb0) => subTermAction(cx, tb0, ta.Symbol) + (ta, tb0) => subTermAction(cx, tb0, ta.Symbol, symbolBeingDefined) ); trapFile.Write('>'); } @@ -273,16 +288,16 @@ namespace Semmle.Extraction.CSharp trapFile.Write('.'); } - static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName) + static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName) { var buildParam = includeParamName ? (prop, tb0) => { tb0.Write(prop.Name); tb0.Write(' '); - subTermAction(cx, tb0, prop.Type); + subTermAction(cx, tb0, prop.Type, null); } - : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type)); + : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type, null)); int memberCount = type.GetMembers().OfType().Count(); int hackTypeNumber = memberCount == 1 ? 1 : 0; trapFile.Write("<>__AnonType"); @@ -354,7 +369,7 @@ namespace Semmle.Extraction.CSharp if (namedType.IsAnonymousType) { - namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub) => sub.BuildDisplayName(cx0, tb0), false); + namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub, _) => sub.BuildDisplayName(cx0, tb0), false); } trapFile.Write(namedType.Name); From abf6be6030f6709e2066ba7bf343dbb789ba02e2 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Wed, 12 Feb 2020 16:23:48 +0000 Subject: [PATCH 337/459] C#: Avoid qualifying explicit interface implementations. --- .../Entities/Method.cs | 11 ++++--- .../Entities/Types/NamedType.cs | 8 ++--- .../Entities/Types/TupleType.cs | 2 +- .../SymbolExtensions.cs | 32 +++++++++++++++---- .../library-tests/aliases/aliases2.expected | 6 ++++ .../csharp8/NullableRefTypes.expected | 4 +-- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 77c9e2ab21d..384ef46dbe9 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -204,7 +204,7 @@ namespace Semmle.Extraction.CSharp.Entities type.BuildTypeId(cx, trapFile, false, symbolBeingDefined, (cx0, tb0, type0, g) => AddSignatureTypeToId(cx, tb0, method, type0, g)); } - protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method, ISymbol generic) + protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method, ISymbol symbolBeingDefined) { trapFile.Write('('); int index = 0; @@ -212,13 +212,13 @@ namespace Semmle.Extraction.CSharp.Entities if (method.MethodKind == MethodKind.ReducedExtension) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, generic); + AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, symbolBeingDefined); } foreach (var param in method.Parameters) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, param.Type, generic); + AddSignatureTypeToId(cx, trapFile, method, param.Type, symbolBeingDefined); switch (param.RefKind) { case RefKind.Out: @@ -241,9 +241,10 @@ namespace Semmle.Extraction.CSharp.Entities public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable explicitInterfaceImplementations) { - if (explicitInterfaceImplementations.Any()) + foreach (var i in explicitInterfaceImplementations) { - trapFile.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType))); + trapFile.Write(';'); + i.ContainingType.BuildNestedTypeId(cx, trapFile, null); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 5611477daf0..25145520aee 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -111,7 +111,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, g) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";type"); } @@ -177,11 +177,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol, ISymbol symbolBeingDefined) - { - symbol.BuildTypeId(cx, trapFile, false, symbolBeingDefined, WriteType); - } - WriteType(Context, trapFile, referencedType.symbol, referencedType.symbol); + referencedType.symbol.BuildNestedTypeId(Context, trapFile, referencedType.symbol); trapFile.Write(";typeRef"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index 4f5e5f68d40..b7e38fd88f4 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, g) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";tuple"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 7acfc502720..17a493771c6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -122,6 +122,24 @@ namespace Semmle.Extraction.CSharp } } + /// + /// Write the identifier for the symbol to the trapfile . + /// If any nested types are found in the identifier, then they are written out explicitly, without + /// prefixing the assembly ID. + /// + /// The type to write. + /// The extraction context. + /// The trap file to write to. + /// The outer symbol being defined (to avoid recursive ids). + public static void BuildNestedTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined) + { + void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol, ISymbol symbolBeingDefined) + { + symbol.BuildTypeId(cx, trapFile, false, symbolBeingDefined, WriteType); + } + WriteType(cx, trapFile, type, symbolBeingDefined); + } + /// /// Constructs a unique string for this type symbol. /// @@ -130,8 +148,10 @@ namespace Semmle.Extraction.CSharp /// /// The extraction context. /// The trap builder used to store the result. + /// Whether to prefix the type ID with the assembly ID. + /// The outer symbol being defined (to avoid recursive ids). /// The action to apply to syntactic sub terms of this type. - public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, ISymbol SymbolBeingDefined, Action subTermAction) + public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, ISymbol symbolBeingDefined, Action subTermAction) { if (type.SpecialType != SpecialType.None && !(type is INamedTypeSymbol n && n.IsGenericType)) { @@ -150,7 +170,7 @@ namespace Semmle.Extraction.CSharp { case TypeKind.Array: var array = (IArrayTypeSymbol)type; - subTermAction(cx, trapFile, array.ElementType, SymbolBeingDefined); + subTermAction(cx, trapFile, array.ElementType, symbolBeingDefined); array.BuildArraySuffix(trapFile); return; case TypeKind.Class: @@ -160,16 +180,16 @@ namespace Semmle.Extraction.CSharp case TypeKind.Delegate: case TypeKind.Error: var named = (INamedTypeSymbol)type; - named.BuildNamedTypeId(cx, trapFile, prefix, SymbolBeingDefined, subTermAction); + named.BuildNamedTypeId(cx, trapFile, prefix, symbolBeingDefined, subTermAction); return; case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; - subTermAction(cx, trapFile, ptr.PointedAtType, SymbolBeingDefined); + subTermAction(cx, trapFile, ptr.PointedAtType, symbolBeingDefined); trapFile.Write('*'); return; case TypeKind.TypeParameter: var tp = (ITypeParameterSymbol)type; - if (!SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, SymbolBeingDefined)) + if (!SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, symbolBeingDefined)) { switch (tp.TypeParameterKind) { @@ -179,7 +199,7 @@ namespace Semmle.Extraction.CSharp trapFile.Write('_'); break; case TypeParameterKind.Type: - subTermAction(cx, trapFile, tp.ContainingType, SymbolBeingDefined); + subTermAction(cx, trapFile, tp.ContainingType, symbolBeingDefined); trapFile.Write('_'); break; } diff --git a/csharp/ql/test/library-tests/aliases/aliases2.expected b/csharp/ql/test/library-tests/aliases/aliases2.expected index 45870c5dda2..05fad62d6a8 100644 --- a/csharp/ql/test/library-tests/aliases/aliases2.expected +++ b/csharp/ql/test/library-tests/aliases/aliases2.expected @@ -1,3 +1,9 @@ | Program.cs:18:21:18:22 | c1 | Assembly1.dll:0:0:0:0 | Class | +| Program.cs:18:21:18:22 | c1 | Assembly2.dll:0:0:0:0 | Class | +| Program.cs:18:21:18:22 | c1 | Program.cs:10:7:10:11 | Class | +| Program.cs:19:21:19:22 | c2 | Assembly1.dll:0:0:0:0 | Class | | Program.cs:19:21:19:22 | c2 | Assembly2.dll:0:0:0:0 | Class | +| Program.cs:19:21:19:22 | c2 | Program.cs:10:7:10:11 | Class | +| Program.cs:20:15:20:16 | c3 | Assembly1.dll:0:0:0:0 | Class | +| Program.cs:20:15:20:16 | c3 | Assembly2.dll:0:0:0:0 | Class | | Program.cs:20:15:20:16 | c3 | Program.cs:10:7:10:11 | Class | diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected index db4f3c6fb5d..ff888cc88dd 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected @@ -241,9 +241,9 @@ expressionTypes | NullableRefTypes.cs:17:29:17:32 | null | null | | NullableRefTypes.cs:18:31:18:34 | this access | MyClass! | | NullableRefTypes.cs:19:33:19:36 | this access | MyClass! | -| NullableRefTypes.cs:26:44:26:53 | throw ... | MyClass![]! | +| NullableRefTypes.cs:26:44:26:53 | throw ... | MyClass?[]! | | NullableRefTypes.cs:26:50:26:53 | null | null | -| NullableRefTypes.cs:27:44:27:53 | throw ... | MyClass![]! | +| NullableRefTypes.cs:27:44:27:53 | throw ... | MyClass?[]! | | NullableRefTypes.cs:27:50:27:53 | null | null | | NullableRefTypes.cs:30:21:30:24 | null | null | | NullableRefTypes.cs:31:20:31:23 | this access | MyClass! | From 6fc814632c5a433435ff8f933e2f78079f485490 Mon Sep 17 00:00:00 2001 From: Pavel Avgustinov Date: Mon, 6 Apr 2020 14:33:32 +0100 Subject: [PATCH 338/459] Relicense under MIT --- CONTRIBUTING.md | 35 +-------- COPYRIGHT | 13 ---- LICENSE | 189 +++++------------------------------------------- 3 files changed, 19 insertions(+), 218 deletions(-) delete mode 100644 COPYRIGHT diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index af8575bc316..9853e6b91b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to CodeQL -We welcome contributions to our CodeQL libraries and queries. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! +We welcome contributions to our CodeQL libraries and queries. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE). There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). @@ -47,10 +47,6 @@ If you have an idea for a query that you would like to share with other CodeQL u - The query must have at least one true positive result on some revision of a real project. -6. **Contributor License Agreement** - - - The contributor can satisfy the [CLA](#contributor-license-agreement). - Experimental queries and libraries may not be actively maintained as the [supported](docs/supported-queries.md) libraries evolve. They may also be changed in backwards-incompatible ways or may be removed entirely in the future without deprecation warnings. After the experimental query is merged, we welcome pull requests to improve it. Before a query can be moved out of the `experimental` subdirectory, it must satisfy [the requirements for being a supported query](docs/supported-queries.md). @@ -65,33 +61,6 @@ normal course of software development. We also store records of your CLA agreements. Under GDPR legislation, we do this on the basis of our legitimate interest in creating the CodeQL product. -Please do get in touch (privacy@semmle.com) if you have any questions about +Please do get in touch (privacy@github.com) if you have any questions about this or our data protection policies. -## Contributor License Agreement - -This Contributor License Agreement (“Agreement”) is entered into between Semmle Limited (“Semmle,” “we” or “us” etc.), and You (as defined and further identified below). - -Accordingly, You hereby agree to the following terms for Your present and future Contributions submitted to Semmle: - -1. **Definitions**. - - * "You" (or "Your") shall mean the Contribution copyright owner (whether an individual or organization) or legal entity authorized by the copyright owner that is making this Agreement with Semmle. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - * "Contribution(s)" shall mean the code, documentation or other original works of authorship, including any modifications or additions to an existing work, submitted by You to Semmle for inclusion in, or documentation of, any of the products or projects owned or managed by Semmle (the "Work(s)"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to Semmle or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Semmle for the purpose of discussing and/or improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." - -2. **Grant of Copyright License**. You hereby grant to Semmle and to recipients of software distributed by Semmle a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. - -3. **Grant of Patent License**. You hereby grant to Semmle and to recipients of software distributed by Semmle a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that Your Contribution, or the Work to which You have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. - -4. **Ownership**. Except as set out above, You keep all right, title, and interest in Your Contribution. The rights that You grant to us under this Agreement are effective on the date You first submitted a Contribution to us, even if Your submission took place before the date You entered this Agreement. - -5. **Representations**. You represent and warrant that: (i) the Contributions are an original work and that You can legally grant the rights set out in this Agreement; (ii) the Contributions and Semmle’s exercise of any license rights granted hereunder, does not and will not, infringe the rights of any third party; (iii) You are not aware of any pending or threatened claims, suits, actions, or charges pertaining to the Contributions, including without limitation any claims or allegations that any or all of the Contributions infringes, violates, or misappropriate the intellectual property rights of any third party (You further agree that You will notify Semmle immediately if You become aware of any such actual or potential claims, suits, actions, allegations or charges). - -6. **Employer**. If Your employer(s) has rights to intellectual property that You create that includes Your Contributions, You represent and warrant that Your employer has waived such rights for Your Contributions to Semmle, or that You have received permission to make Contributions on behalf of that employer and that You are authorized to execute this Agreement on behalf of Your employer. - -7. **Inclusion of Code**. We determine the code that is in our Works. You understand that the decision to include the Contribution in any project or source repository is entirely that of Semmle, and this agreement does not guarantee that the Contributions will be included in any product. - -8. **Disclaimer**. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Except as set forth herein, and unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. - -9. **General**. The failure of either party to enforce its rights under this Agreement for any period shall not be construed as a waiver of such rights. No changes or modifications or waivers to this Agreement will be effective unless in writing and signed by both parties. In the event that any provision of this Agreement shall be determined to be illegal or unenforceable, that provision will be limited or eliminated to the minimum extent necessary so that this Agreement shall otherwise remain in full force and effect and enforceable. This Agreement shall be governed by and construed in accordance with the laws of the State of California in the United States without regard to the conflicts of laws provisions thereof. In any action or proceeding to enforce rights under this Agreement, the prevailing party will be entitled to recover costs and attorneys’ fees. diff --git a/COPYRIGHT b/COPYRIGHT deleted file mode 100644 index 65d947ff274..00000000000 --- a/COPYRIGHT +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) Semmle Inc and other contributors. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. diff --git a/LICENSE b/LICENSE index d9a10c0d8e8..e29b05cd648 100644 --- a/LICENSE +++ b/LICENSE @@ -1,176 +1,21 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +MIT License - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Copyright (c) 2006-2020 GitHub, Inc. - 1. Definitions. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 7af5f038aba000e5467416f87b5024f97acebcd8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 7 Apr 2020 14:02:53 +0200 Subject: [PATCH 339/459] Python: Add missing override to ClassValue.hasAttribute I was considering if this was actually something different than Value.hasAttribute, and the names were just accidentially the same. But after looking at the definition for Value, I'm happy about marking this as an override (I did not test whether it was neede though): ```codeql class Value extends TObject { ... /** Holds if this value has the attribute `name` */ predicate hasAttribute(string name) { this.(ObjectInternal).hasAttribute(name) } ``` --- python/ql/src/semmle/python/objects/ObjectAPI.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 9772a77ed8b..a3d6431b448 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -540,10 +540,10 @@ class ClassValue extends Value { Value declaredAttribute(string name) { Types::declaredAttribute(this, name, result, _) } /** - * Holds if this class has the attribute `name`, including - * attributes declared by super classes. + * Holds if this class has the attribute `name`, including attributes + * declared by super classes. */ - predicate hasAttribute(string name) { this.getMro().declares(name) } + override predicate hasAttribute(string name) { this.getMro().declares(name) } /** * Holds if this class declares the attribute `name`, From d56284fe8fc0aeadf674bc4e118aa85de54b8228 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 7 Apr 2020 16:00:40 +0200 Subject: [PATCH 340/459] C++: Move added flow from simpleLocalFlowStep to simpleInstructionLocalFlowStep and remove flow that could cause field conflation --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 17 +++++------------ .../dataflow/dataflow-tests/test_diff.expected | 4 +++- .../dataflow/dataflow-tests/test_ir.expected | 4 ---- .../dataflow/taint-tests/test_diff.expected | 4 +--- .../dataflow/taint-tests/test_ir.expected | 4 ---- .../literals/literals/literals.expected | 8 ++++---- 6 files changed, 13 insertions(+), 28 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index a7a5f9d6d86..91c089959dc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -385,13 +385,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr */ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) - or - exists(LoadInstruction load, ChiInstruction chi | - not chi.isResultConflated() and - nodeTo.asInstruction() = load and - nodeFrom.asInstruction() = chi and - load.getSourceValueOperand().getAnyDef() = chi - ) } private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) { @@ -417,13 +410,13 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // // Flow through the partial operand belongs in the taint-tracking libraries // for now. - // TODO: To capture flow from a partial definition of an object (i.e., a field write) to the object - // we add dataflow through partial chi operands, but only if the chi node is not the chi node for all - // aliased memory. - iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom and not iTo.isResultConflated() - or iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or + exists(ChiInstruction chi | iFrom = chi | + not chi.isResultConflated() and + iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi + ) + or // Flow through modeled functions modelFlow(iFrom, iTo) } diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 11c5acc30fc..71630f892f5 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -2,7 +2,6 @@ | BarrierGuard.cpp:60:11:60:16 | BarrierGuard.cpp:62:14:62:14 | AST only | | clang.cpp:12:9:12:20 | clang.cpp:22:8:22:20 | AST only | | clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only | -| clang.cpp:28:27:28:32 | clang.cpp:31:27:31:28 | IR only | | clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only | @@ -46,6 +45,9 @@ | test.cpp:359:13:359:18 | test.cpp:365:10:365:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:369:10:369:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:375:10:375:14 | AST only | +| test.cpp:382:48:382:54 | test.cpp:385:8:385:10 | AST only | +| test.cpp:388:53:388:59 | test.cpp:392:8:392:10 | AST only | +| test.cpp:388:53:388:59 | test.cpp:394:10:394:12 | AST only | | test.cpp:399:7:399:9 | test.cpp:401:8:401:10 | AST only | | test.cpp:405:7:405:9 | test.cpp:408:8:408:10 | AST only | | test.cpp:416:7:416:11 | test.cpp:418:8:418:12 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index f4e072d1905..275cbabc075 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -12,7 +12,6 @@ | clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 | | clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 | | clang.cpp:29:27:29:28 | m1 | clang.cpp:28:27:28:32 | call to source | -| clang.cpp:31:27:31:28 | m2 | clang.cpp:28:27:28:32 | call to source | | clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source | | clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source | | clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source | @@ -62,9 +61,6 @@ | test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source | | test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source | | test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source | -| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 | -| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 | -| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 | | test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 | | test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 | | true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | 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 ffe098d6063..329a0bb6ecc 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 @@ -17,15 +17,13 @@ | taint.cpp:93:11:93:11 | taint.cpp:71:22:71:27 | AST only | | taint.cpp:94:11:94:11 | taint.cpp:72:7:72:12 | AST only | | taint.cpp:109:7:109:13 | taint.cpp:105:12:105:17 | IR only | -| taint.cpp:110:7:110:13 | taint.cpp:105:12:105:17 | IR only | -| taint.cpp:111:7:111:13 | taint.cpp:106:12:106:17 | IR only | -| taint.cpp:112:7:112:13 | taint.cpp:106:12:106:17 | IR only | | taint.cpp:130:7:130:9 | taint.cpp:127:8:127:13 | IR only | | taint.cpp:137:7:137:9 | taint.cpp:120:11:120:16 | AST only | | taint.cpp:173:8:173:13 | taint.cpp:164:19:164:24 | AST only | | taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only | +| taint.cpp:216:7:216:7 | taint.cpp:207:6:207:11 | AST only | | taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | 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 e6f138e6283..b0107791e61 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 @@ -2,9 +2,6 @@ | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | | taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source | -| taint.cpp:110:7:110:13 | access to array | taint.cpp:105:12:105:17 | call to source | -| taint.cpp:111:7:111:13 | access to array | taint.cpp:106:12:106:17 | call to source | -| taint.cpp:112:7:112:13 | access to array | taint.cpp:106:12:106:17 | call to source | | taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source | | taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source | | taint.cpp:134:7:134:9 | * ... | taint.cpp:120:11:120:16 | call to source | @@ -13,7 +10,6 @@ | taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source | | taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source | -| taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source | | taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source | | taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source | | taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source | diff --git a/cpp/ql/test/library-tests/literals/literals/literals.expected b/cpp/ql/test/library-tests/literals/literals/literals.expected index a3fd43a7f04..4e640c9b2dc 100644 --- a/cpp/ql/test/library-tests/literals/literals/literals.expected +++ b/cpp/ql/test/library-tests/literals/literals/literals.expected @@ -2,10 +2,10 @@ | literals.c:3:13:3:16 | 1.0 | | literals.c:4:13:4:16 | 1.0 | | literals.c:5:13:5:16 | 1.0 | -| literals.c:6:13:6:16 | (0.0,1.0i) | -| literals.c:7:13:7:16 | (0.0,1.0i) | -| literals.c:8:13:8:16 | (0.0,1.0i) | -| literals.c:9:13:9:16 | (0.0,1.0i) | +| literals.c:6:13:6:16 | (1.0,1.0i) | +| literals.c:7:13:7:16 | (1.0,1.0i) | +| literals.c:8:13:8:16 | (1.0,1.0i) | +| literals.c:9:13:9:16 | (1.0,1.0i) | | literals.c:10:13:10:16 | 1.0 | | literals.c:11:13:11:16 | 1.0 | | literals.c:12:13:12:16 | 1.0 | From 39911af56b2eb80b250869cc398df43e59f25f32 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 7 Apr 2020 15:47:49 +0200 Subject: [PATCH 341/459] C++: Avoid partial chi flow to struct/class Flow through partial chi-instruction operands was introduced to make definition-by-reference work, but its implementation also allowed all other partial writes to propagate. In particular, tainting a field would taint the whole struct, which in turn led to taint propagating across unrelated fields of a struct. The security test `CWE-134/semmle/argv/argvLocal.c` shows that we also want to propagate taint from an array element to the whole array, and it also seems right to propagate taint from a union member to the whole union. --- .../code/cpp/ir/dataflow/DefaultTaintTracking.qll | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 2cec0dc2a5a..68efa133100 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -189,9 +189,22 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { or i2.(UnaryInstruction).getUnary() = i1 or - i2.(ChiInstruction).getPartial() = i1 and + // Flow out of definition-by-reference + i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and not i2.isResultConflated() or + // Flow from an element to an array or union that contains it. + i2.(ChiInstruction).getPartial() = i1 and + not i2.isResultConflated() and + exists(Type t | i2.getResultLanguageType().hasType(t, false) | + t instanceof Union + or + t instanceof ArrayType + or + // Buffers or unknown size + t instanceof UnknownType + ) + or exists(BinaryInstruction bin | bin = i2 and predictableInstruction(i2.getAnOperand().getDef()) and From ff39f714e8adc9bfbe5f07f5dd96d74cacf4b1f3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:07:31 +0100 Subject: [PATCH 342/459] C++: Autoformat. --- cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 2 +- cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 0a38b27ee4e..a48efbe9e64 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -135,7 +135,7 @@ private predicate writesVariable(StoreInstruction store, Variable var) { * upper bounds checks if we don't consider where it occurs, for example: * ``` * if (x < 10) { sink(x); } - * + * * if (10 > y) { sink(y); } * * if (z > 10) { z = 10; } diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll index c0d9ef6a912..a24820b277f 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -333,7 +333,7 @@ GlobalOrNamespaceVariable globalVarFromId(string id) { * upper bounds checks if we don't consider where it occurs, for example: * ``` * if (x < 10) { sink(x); } - * + * * if (10 > y) { sink(y); } * * if (z > 10) { z = 10; } From 2686d9888cdfdc12eb14b7685cb806b5d39897ef Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 7 Apr 2020 18:10:56 +0100 Subject: [PATCH 343/459] C++: Add QLDoc. --- .../semmle/code/cpp/models/implementations/Allocation.qll | 8 +++++++- .../code/cpp/models/implementations/Deallocation.qll | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index c6766983889..d2577dc3ca4 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -1,4 +1,10 @@ -import semmle.code.cpp.models.interfaces.Allocation +/** + * Provides implementation classes modelling various methods of allocation + * (`malloc`, `new` etc). See `semmle.code.cpp.models.interfaces.Allocation` + * for usage information. + */ + + import semmle.code.cpp.models.interfaces.Allocation /** * An allocation function (such as `malloc`) that has an argument for the size diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index d2e4951e436..6637c6e1b26 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -1,4 +1,10 @@ -import semmle.code.cpp.models.interfaces.Allocation +/** + * Provides implementation classes modelling various methods of deallocation + * (`free`, `delete` etc). See `semmle.code.cpp.models.interfaces.Deallocation` + * for usage information. + */ + + import semmle.code.cpp.models.interfaces.Allocation /** * A deallocation function such as `free`. From 1f496d3c6b3fd3f61f096910a748b789ba503592 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 7 Apr 2020 19:02:46 +0100 Subject: [PATCH 344/459] JS: Add CapturedVariableNode --- .../ql/src/semmle/javascript/Variables.qll | 13 +++++ .../semmle/javascript/dataflow/DataFlow.qll | 50 +++++++++++++++---- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Variables.qll b/javascript/ql/src/semmle/javascript/Variables.qll index 5c5c3e3f115..bef027d6fbd 100644 --- a/javascript/ql/src/semmle/javascript/Variables.qll +++ b/javascript/ql/src/semmle/javascript/Variables.qll @@ -317,6 +317,19 @@ class LocalVariable extends Variable { else result = d.getContainer() ) } + + /** + * Gets the location of a declaration of this variable. + * + * If the variable has multiple declarations, an arbitrary one is used. + * If it has no declaration, the location of its declaring scope is used. + */ + Location getLocation() { + result = min(Location loc | loc = getADeclaration().getLocation() | loc order by loc.getStartLine(), loc.getStartColumn() ) + or + not exists(getADeclaration()) and + result = getDeclaringContainer().getLocation() + } } /** A local variable that is not captured. */ diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 5d7ce03e467..d4d7e3bff16 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -27,6 +27,7 @@ module DataFlow { private newtype TNode = TValueNode(AST::ValueNode nd) or TSsaDefNode(SsaDefinition d) or + TCapturedVariableNode(LocalVariable v) { v.isCaptured() } or TPropNode(@property p) or TRestPatternNode(DestructuringPattern dp, Expr rest) { rest = dp.getRest() } or TDestructuringPatternNode(DestructuringPattern dp) or @@ -1221,6 +1222,29 @@ module DataFlow { } } + /** + * A data flow node representing a captured variable. + */ + private class CapturedVariableNode extends Node, TCapturedVariableNode { + LocalVariable variable; + + CapturedVariableNode() { this = TCapturedVariableNode(variable) } + + override BasicBlock getBasicBlock() { + result = variable.getDeclaringContainer().getStartBB() + } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + variable.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + override string toString() { + result = variable.getName() + } + } + /** * Gets the data flow node corresponding to `nd`. * @@ -1434,19 +1458,23 @@ module DataFlow { or immediateFlowStep(pred, succ) or + // From an assignment or implicit initialization of a captured variable to its flow-insensitive node. + exists(SsaDefinition predDef | + pred = TSsaDefNode(predDef) and + succ = TCapturedVariableNode(predDef.getSourceVariable()) + | + predDef instanceof SsaExplicitDefinition or + predDef instanceof SsaImplicitInit + ) + or + // From a captured variable node to its flow-sensitive capture nodes + exists(SsaVariableCapture ssaCapture | + pred = TCapturedVariableNode(ssaCapture.getSourceVariable()) and + succ = TSsaDefNode(ssaCapture) + ) + or // Flow through implicit SSA nodes exists(SsaImplicitDefinition ssa | succ = TSsaDefNode(ssa) | - // from any explicit definition or implicit init of a captured variable into - // the capturing definition - exists(SsaSourceVariable v, SsaDefinition predDef | - v = ssa.(SsaVariableCapture).getSourceVariable() and - predDef.getSourceVariable() = v and - pred = TSsaDefNode(predDef) - | - predDef instanceof SsaExplicitDefinition or - predDef instanceof SsaImplicitInit - ) - or // from the inputs of phi and pi nodes into the node itself pred = TSsaDefNode(ssa.(SsaPseudoDefinition).getAnInput().getDefinition()) ) From 4c7d413fa478329807686e6ea768752d4fb8cad5 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Tue, 7 Apr 2020 19:58:48 +0100 Subject: [PATCH 345/459] C#: Address review comment. --- .../Semmle.Extraction.CSharp/Entities/Constructor.cs | 2 +- .../extractor/Semmle.Extraction.CSharp/Entities/Method.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs index 3230ad699f6..298f838cfb9 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs @@ -114,7 +114,7 @@ namespace Semmle.Extraction.CSharp.Entities { if (symbol.IsStatic) trapFile.Write("static"); trapFile.WriteSubId(ContainingType); - AddParametersToId(Context, trapFile, symbol, symbol); + AddParametersToId(Context, trapFile, symbol); trapFile.Write(";constructor"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 384ef46dbe9..7fe73cde06d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -134,7 +134,7 @@ namespace Semmle.Extraction.CSharp.Entities } } - AddParametersToId(m.Context, trapFile, m.symbol, m.symbol); + AddParametersToId(m.Context, trapFile, m.symbol); switch (m.symbol.MethodKind) { case MethodKind.PropertyGet: @@ -204,7 +204,7 @@ namespace Semmle.Extraction.CSharp.Entities type.BuildTypeId(cx, trapFile, false, symbolBeingDefined, (cx0, tb0, type0, g) => AddSignatureTypeToId(cx, tb0, method, type0, g)); } - protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method, ISymbol symbolBeingDefined) + protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method) { trapFile.Write('('); int index = 0; @@ -212,13 +212,13 @@ namespace Semmle.Extraction.CSharp.Entities if (method.MethodKind == MethodKind.ReducedExtension) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, symbolBeingDefined); + AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, method); } foreach (var param in method.Parameters) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, param.Type, symbolBeingDefined); + AddSignatureTypeToId(cx, trapFile, method, param.Type, method); switch (param.RefKind) { case RefKind.Out: From 50194f372b8a55bce887288d7916837873ef89b8 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 7 Apr 2020 20:54:54 +0100 Subject: [PATCH 346/459] C++: Autoformat. --- .../src/semmle/code/cpp/models/implementations/Allocation.qll | 2 +- .../src/semmle/code/cpp/models/implementations/Deallocation.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index d2577dc3ca4..f6f7ab279a6 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -4,7 +4,7 @@ * for usage information. */ - import semmle.code.cpp.models.interfaces.Allocation +import semmle.code.cpp.models.interfaces.Allocation /** * An allocation function (such as `malloc`) that has an argument for the size diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 6637c6e1b26..60076ed28d7 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -4,7 +4,7 @@ * for usage information. */ - import semmle.code.cpp.models.interfaces.Allocation +import semmle.code.cpp.models.interfaces.Allocation /** * A deallocation function such as `free`. From 7fedac3266f8bbcfda9d5892c01eb5c158391746 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 7 Apr 2020 20:56:07 +0100 Subject: [PATCH 347/459] C++: Fix apparently noncritical typo. --- .../src/semmle/code/cpp/models/implementations/Deallocation.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 60076ed28d7..980645df031 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -4,7 +4,7 @@ * for usage information. */ -import semmle.code.cpp.models.interfaces.Allocation +import semmle.code.cpp.models.interfaces.Deallocation /** * A deallocation function such as `free`. From 96a0bddcf6063d132a30301bbf0fe95fcf16eebf Mon Sep 17 00:00:00 2001 From: Disconnect3d Date: Tue, 7 Apr 2020 22:30:57 +0200 Subject: [PATCH 348/459] Update ReturnConstTypeMember.cpp --- cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp b/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp index cc6b6da3abb..ad3d7d3c9e1 100644 --- a/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp +++ b/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp @@ -8,6 +8,6 @@ struct S { // Whereas here it does make a semantic difference. auto getValCorrect() const -> int { - return val + return val; } }; From 9d2f76849b01ebd586a6ed9b871d1ac3242df4db Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Mon, 17 Feb 2020 23:05:00 -0500 Subject: [PATCH 349/459] Java 14: switch expressions are no longer in preview --- java/ql/src/semmle/code/java/Expr.qll | 2 -- java/ql/src/semmle/code/java/Statement.qll | 12 ------------ java/ql/test/library-tests/guards12/options | 2 +- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index 37cc608d878..eff4928fd46 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -1076,8 +1076,6 @@ class ConditionalExpr extends Expr, @conditionalexpr { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * A `switch` expression. */ class SwitchExpr extends Expr, @switchexpr { diff --git a/java/ql/src/semmle/code/java/Statement.qll b/java/ql/src/semmle/code/java/Statement.qll index 2a5f94ef781..fa303a7c3ee 100755 --- a/java/ql/src/semmle/code/java/Statement.qll +++ b/java/ql/src/semmle/code/java/Statement.qll @@ -417,8 +417,6 @@ class SwitchCase extends Stmt, @case { SwitchStmt getSwitch() { result.getACase() = this } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the switch expression to which this case belongs, if any. */ SwitchExpr getSwitchExpr() { result.getACase() = this } @@ -432,8 +430,6 @@ class SwitchCase extends Stmt, @case { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Holds if this `case` is a switch labeled rule of the form `... -> ...`. */ predicate isRule() { @@ -443,15 +439,11 @@ class SwitchCase extends Stmt, @case { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the expression on the right-hand side of the arrow, if any. */ Expr getRuleExpression() { result.getParent() = this and result.getIndex() = -1 } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the statement on the right-hand side of the arrow, if any. */ Stmt getRuleStatement() { result.getParent() = this and result.getIndex() = -1 } @@ -465,8 +457,6 @@ class ConstCase extends SwitchCase { Expr getValue() { result.getParent() = this and result.getIndex() = 0 } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the `case` constant at the specified index. */ Expr getValue(int i) { result.getParent() = this and result.getIndex() = i and i >= 0 } @@ -624,8 +614,6 @@ class BreakStmt extends Stmt, @breakstmt { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * A `yield` statement. */ class YieldStmt extends Stmt, @yieldstmt { diff --git a/java/ql/test/library-tests/guards12/options b/java/ql/test/library-tests/guards12/options index 99827347b32..3f12170222c 100644 --- a/java/ql/test/library-tests/guards12/options +++ b/java/ql/test/library-tests/guards12/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --enable-preview -source 13 -target 13 +//semmle-extractor-options: --javac-args -source 14 -target 14 From b7633422771347dd57d7de5d00c4f706b4350633 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sat, 22 Feb 2020 14:08:06 -0500 Subject: [PATCH 350/459] Java 14: account for `instanceof` pattern matching --- java/ql/src/semmle/code/java/Expr.qll | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index eff4928fd46..ccef5f3829a 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -1130,7 +1130,17 @@ deprecated class ParExpr extends Expr, @parexpr { /** An `instanceof` expression. */ class InstanceOfExpr extends Expr, @instanceofexpr { /** Gets the expression on the left-hand side of the `instanceof` operator. */ - Expr getExpr() { result.isNthChildOf(this, 0) } + Expr getExpr() { + if isPattern() + then result = getLocalVariableDeclExpr().getInit() + else result.isNthChildOf(this, 0) + } + + /** Holds if this `instanceof` expression uses pattern matching. */ + predicate isPattern() { exists(getLocalVariableDeclExpr()) } + + /** Gets the local variable declaration of this `instanceof` expression if pattern matching is used. */ + LocalVariableDeclExpr getLocalVariableDeclExpr() { result.isNthChildOf(this, 0) } /** Gets the access to the type on the right-hand side of the `instanceof` operator. */ Expr getTypeName() { result.isNthChildOf(this, 1) } @@ -1161,6 +1171,8 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr { exists(ForStmt fs | fs.getAnInit() = this | result.isNthChildOf(fs, 0)) or exists(EnhancedForStmt efs | efs.getVariable() = this | result.isNthChildOf(efs, -1)) + or + exists(InstanceOfExpr ioe | this.getParent() = ioe | result.isNthChildOf(ioe, 1)) } /** Gets the name of the variable declared by this local variable declaration expression. */ From e1787f58aa0df72b52cc5fdf10b1279606941446 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sat, 7 Mar 2020 22:27:18 -0500 Subject: [PATCH 351/459] Java 14: add `isRecord` relation to dbscheme --- java/ql/src/config/semmlecode.dbscheme | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/ql/src/config/semmlecode.dbscheme b/java/ql/src/config/semmlecode.dbscheme index 054d7e823b2..2a682863863 100755 --- a/java/ql/src/config/semmlecode.dbscheme +++ b/java/ql/src/config/semmlecode.dbscheme @@ -268,6 +268,10 @@ classes( int sourceid: @class ref ); +isRecord( + unique int id: @class ref +); + interfaces( unique int id: @interface, string nodeName: string ref, From 662cff831640a8dca8a47ba7a85d553dcee6de03 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sat, 7 Mar 2020 22:27:47 -0500 Subject: [PATCH 352/459] Java 14: add class `Record` to `Type.qll` --- java/ql/src/semmle/code/java/Type.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/ql/src/semmle/code/java/Type.qll b/java/ql/src/semmle/code/java/Type.qll index f08c5a5eea4..b34e165a4ff 100755 --- a/java/ql/src/semmle/code/java/Type.qll +++ b/java/ql/src/semmle/code/java/Type.qll @@ -615,6 +615,11 @@ class Class extends RefType, @class { } } +/** A record declaration. */ +class Record extends Class { + Record() { isRecord(this) } +} + /** An intersection type. */ class IntersectionType extends RefType, @class { IntersectionType() { From 70e09ddb8878352e520f7a70df8ff3cc8c9a0844 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sun, 8 Mar 2020 12:34:45 -0400 Subject: [PATCH 353/459] Java 14: add dbscheme stats for records --- java/ql/src/config/semmlecode.dbscheme.stats | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/java/ql/src/config/semmlecode.dbscheme.stats b/java/ql/src/config/semmlecode.dbscheme.stats index 165db4674b5..ae0f5e3b34f 100644 --- a/java/ql/src/config/semmlecode.dbscheme.stats +++ b/java/ql/src/config/semmlecode.dbscheme.stats @@ -9263,6 +9263,17 @@ +isRecord +100 + + +id +100 + + + + + interfaces 249736 From e12de3b021bdb95fa5160f99f10df086116643e2 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sun, 8 Mar 2020 12:35:15 -0400 Subject: [PATCH 354/459] Java 14: add dbscheme upgrade script for records --- .../old.dbscheme | 950 +++++++++++++++++ .../semmlecode.dbscheme | 954 ++++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 1906 insertions(+) create mode 100755 java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/old.dbscheme create mode 100755 java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/semmlecode.dbscheme create mode 100644 java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/upgrade.properties diff --git a/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/old.dbscheme b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/old.dbscheme new file mode 100755 index 00000000000..054d7e823b2 --- /dev/null +++ b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/old.dbscheme @@ -0,0 +1,950 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref // deprecated +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +classes( + unique int id: @class, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @class ref +); + +interfaces( + unique int id: @interface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @interface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @interface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @class ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @typeorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @typeorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @class ref, + int parent: @classinstancexpr ref +); + +#keyset[classid] #keyset[parent] +isLocalClass( + int classid: @class ref, + int parent: @localclassdeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @interface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @typeorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localclassdeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +; + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@typeorpackage = @type | @package; + +@typeorcallable = @type | @callable; +@classorinterface = @interface | @class; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype; +@classorarray = @class | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; +@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field | + @annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl; + +@modifiable = @member_modifiable| @param | @localvar ; + +@member_modifiable = @class | @interface | @method | @constructor | @field ; + +@member = @method | @constructor | @field | @reftype ; + +@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception + | @boundedtype | @typebound | @array | @primitive + | @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText + | @xmllocatable; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/semmlecode.dbscheme b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/semmlecode.dbscheme new file mode 100755 index 00000000000..2a682863863 --- /dev/null +++ b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/semmlecode.dbscheme @@ -0,0 +1,954 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref // deprecated +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +classes( + unique int id: @class, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @class ref +); + +isRecord( + unique int id: @class ref +); + +interfaces( + unique int id: @interface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @interface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @interface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @class ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @typeorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @typeorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @class ref, + int parent: @classinstancexpr ref +); + +#keyset[classid] #keyset[parent] +isLocalClass( + int classid: @class ref, + int parent: @localclassdeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @interface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @typeorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localclassdeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +; + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@typeorpackage = @type | @package; + +@typeorcallable = @type | @callable; +@classorinterface = @interface | @class; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype; +@classorarray = @class | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; +@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field | + @annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl; + +@modifiable = @member_modifiable| @param | @localvar ; + +@member_modifiable = @class | @interface | @method | @constructor | @field ; + +@member = @method | @constructor | @field | @reftype ; + +@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception + | @boundedtype | @typebound | @array | @primitive + | @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText + | @xmllocatable; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/upgrade.properties b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/upgrade.properties new file mode 100644 index 00000000000..d42c96673ad --- /dev/null +++ b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/upgrade.properties @@ -0,0 +1,2 @@ +description: Java 14: add `isRecord` relation +compatibility: backwards From 697b273e32433f08966a274eba693394e9d75fa6 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sat, 28 Mar 2020 21:27:50 -0400 Subject: [PATCH 355/459] Java 14: update expected test output --- java/ql/test/library-tests/structure/DeclaresMember.expected | 1 - 1 file changed, 1 deletion(-) diff --git a/java/ql/test/library-tests/structure/DeclaresMember.expected b/java/ql/test/library-tests/structure/DeclaresMember.expected index f4a9c678cc3..32c5f05891b 100644 --- a/java/ql/test/library-tests/structure/DeclaresMember.expected +++ b/java/ql/test/library-tests/structure/DeclaresMember.expected @@ -28,7 +28,6 @@ | LocalClass | LocalClass | | LocalClass | n | | MemberClass | MemberClass | -| Object | | | Object | Object | | Object | clone | | Object | equals | From 9a79e3be2c7296564646e3d6cf375ae6d17d2779 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sun, 5 Apr 2020 12:27:49 -0400 Subject: [PATCH 356/459] Java 14: add `PREVIEW FEATURE` notes to QLDoc --- java/ql/src/semmle/code/java/Expr.qll | 12 ++++++++++-- java/ql/src/semmle/code/java/Type.qll | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index ccef5f3829a..73475f6cc70 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -1136,10 +1136,18 @@ class InstanceOfExpr extends Expr, @instanceofexpr { else result.isNthChildOf(this, 0) } - /** Holds if this `instanceof` expression uses pattern matching. */ + /** + * PREVIEW FEATURE in Java 14. Subject to removal in a future release. + * + * Holds if this `instanceof` expression uses pattern matching. + */ predicate isPattern() { exists(getLocalVariableDeclExpr()) } - /** Gets the local variable declaration of this `instanceof` expression if pattern matching is used. */ + /** + * PREVIEW FEATURE in Java 14. Subject to removal in a future release. + * + * Gets the local variable declaration of this `instanceof` expression if pattern matching is used. + */ LocalVariableDeclExpr getLocalVariableDeclExpr() { result.isNthChildOf(this, 0) } /** Gets the access to the type on the right-hand side of the `instanceof` operator. */ diff --git a/java/ql/src/semmle/code/java/Type.qll b/java/ql/src/semmle/code/java/Type.qll index b34e165a4ff..35f35d44928 100755 --- a/java/ql/src/semmle/code/java/Type.qll +++ b/java/ql/src/semmle/code/java/Type.qll @@ -615,7 +615,11 @@ class Class extends RefType, @class { } } -/** A record declaration. */ +/** + * PREVIEW FEATURE in Java 14. Subject to removal in a future release. + * + * A record declaration. + */ class Record extends Class { Record() { isRecord(this) } } From 2b3ad6042b80621b04219a7f9cdb7395e78502e6 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sun, 5 Apr 2020 12:30:51 -0400 Subject: [PATCH 357/459] Java 14: update supported language version in docs --- docs/language/support/versions-compilers.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/support/versions-compilers.rst b/docs/language/support/versions-compilers.rst index 2f4091139ea..3b244e592bd 100644 --- a/docs/language/support/versions-compilers.rst +++ b/docs/language/support/versions-compilers.rst @@ -15,7 +15,7 @@ .NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go`` - Java,"Java 6 to 13 [4]_","javac (OpenJDK and Oracle JDK), + Java,"Java 6 to 14 [4]_","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [5]_",``.java`` JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" @@ -27,7 +27,7 @@ .. [1] Support for the clang-cl compiler is preliminary. .. [2] Support for the Arm Compiler (armcc) is preliminary. .. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0. - .. [4] Builds that execute on Java 6 to 12 can be analyzed. The analysis understands Java 12 language features. + .. [4] Builds that execute on Java 6 to 14 can be analyzed. The analysis understands Java 14 standard language features. .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. From 0d65db148fbd25b73ee6ea0fe5821ee88f6c6e4c Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 7 Apr 2020 21:14:25 -0700 Subject: [PATCH 358/459] Python: ObjectAPI to ValueAPI: IterReturnsNonIterator: Adds preliminary modernization --- python/ql/src/Functions/IterReturnsNonIterator.ql | 10 +++++----- .../Functions/general/IterReturnsNonIterator.expected | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/python/ql/src/Functions/IterReturnsNonIterator.ql b/python/ql/src/Functions/IterReturnsNonIterator.ql index 67db4e89aa3..20e3d311fa8 100644 --- a/python/ql/src/Functions/IterReturnsNonIterator.ql +++ b/python/ql/src/Functions/IterReturnsNonIterator.ql @@ -12,17 +12,17 @@ import python -ClassObject return_type(FunctionObject f) { +ClassValue return_type(FunctionValue f) { exists(ControlFlowNode n, Return ret | - ret.getScope() = f.getFunction() and + ret.getScope() = f.getScope() and ret.getValue() = n.getNode() and - n.refersTo(_, result, _) + result = n.pointsTo().getClass() ) } -from ClassObject iterable, FunctionObject iter, ClassObject iterator +from ClassValue iterable, FunctionValue iter, ClassValue iterator where - iter = iterable.lookupAttribute("__iter__") and + iter = iterable.lookup("__iter__") and iterator = return_type(iter) and not iterator.isIterator() select iterator, diff --git a/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected b/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected index 2393f18674a..5f0c2c4797c 100644 --- a/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected +++ b/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected @@ -1,4 +1,4 @@ -| file://:Compiled Code:0:0:0:0 | builtin-class object | Class object is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:16:5:16:23 | Function __iter__ | __iter__ | -| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:22:5:22:23 | Function __iter__ | __iter__ | -| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:27:5:27:23 | Function __iter__ | __iter__ | -| protocols.py:30:1:30:26 | class IteratorMissingIter | Class IteratorMissingIter is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:40:5:40:23 | Function __iter__ | __iter__ | +| file://:0:0:0:0 | builtin-class object | Class object is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:16:5:16:23 | Function X.__iter__ | __iter__ | +| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:22:5:22:23 | Function IteratorMissingNext.__iter__ | __iter__ | +| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:27:5:27:23 | Function IterableMissingNext.__iter__ | __iter__ | +| protocols.py:30:1:30:26 | class IteratorMissingIter | Class IteratorMissingIter is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:40:5:40:23 | Function IterableMissingIter.__iter__ | __iter__ | From c2443f2342a20a0abd04f51be57b40d694b51e4b Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Tue, 7 Apr 2020 21:31:35 -0700 Subject: [PATCH 359/459] Python: ObjectAPI to ValueAPI: OverlyComplexDelMethod: Adds preliminary modernization --- python/ql/src/Functions/OverlyComplexDelMethod.ql | 6 +++--- .../Functions/general/OverlyComplexDelMethod.expected | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/Functions/OverlyComplexDelMethod.ql b/python/ql/src/Functions/OverlyComplexDelMethod.ql index 2503f7ac6a7..b709af7fb11 100644 --- a/python/ql/src/Functions/OverlyComplexDelMethod.ql +++ b/python/ql/src/Functions/OverlyComplexDelMethod.ql @@ -15,10 +15,10 @@ import python -from FunctionObject method +from FunctionValue method where - exists(ClassObject c | + exists(ClassValue c | c.declaredAttribute("__del__") = method and - method.getFunction().getMetrics().getCyclomaticComplexity() > 3 + method.getScope().getMetrics().getCyclomaticComplexity() > 3 ) select method, "Overly complex '__del__' method." diff --git a/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected b/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected index 84c08d89426..2eff178d972 100644 --- a/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected +++ b/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected @@ -1 +1 @@ -| protocols.py:74:5:74:22 | Function __del__ | Overly complex '__del__' method. | +| protocols.py:74:5:74:22 | Function MegaDel.__del__ | Overly complex '__del__' method. | From 7a3b310d8df29e1560417d5fe03252e47744e798 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 8 Apr 2020 09:26:19 +0100 Subject: [PATCH 360/459] docs: clarify 'query help' usage --- docs/query-help-style-guide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/query-help-style-guide.md b/docs/query-help-style-guide.md index 58e2d93f95e..4010c91dba7 100644 --- a/docs/query-help-style-guide.md +++ b/docs/query-help-style-guide.md @@ -16,7 +16,7 @@ Query help files must have the same base name as the query they describe and mus ### File structure and layout -Query files are written using an XML format called Qhelp, and stored in a file with a `.qhelp` extension. The basic structure is as follows: +Query files are written using a custom XML format, and stored in a file with a `.qhelp` extension. The basic structure is as follows: ``` @@ -25,7 +25,7 @@ Query files are written using an XML format called Qhelp, and stored in a file w ``` -The header and single top-level `qhelp` element are both mandatory. +The header and single top-level `` element are both mandatory. ### Section-level elements @@ -36,7 +36,7 @@ Section-level elements are used to group the information within the query help f 3. `example`—an example of code showing the problem. Where possible, this section should also include a solution to the issue. 4. `references`—relevant references, such as authoritative sources on language semantics and best practice. -For further information about the other section-level, block, list and table elements supported by the qhelp format, see the [Query help reference](https://help.semmle.com/QL/learn-ql/ql/writing-queries/query-help.html) on help.semmle.com. +For further information about the other section-level, block, list and table elements supported by query help files, see the [Query help reference](https://help.semmle.com/QL/learn-ql/ql/writing-queries/query-help.html) on help.semmle.com. ## English style @@ -86,7 +86,7 @@ For example: >W. C. Wake, _Refactoring Workbook_, pp. 93 – 94, Addison-Wesley Professional, 2004. -Note, & symbols need to be replaced by \&. The symbol will be displayed correctly in the html files generated from the qhelp files. +Note, & symbols need to be replaced by \&. The symbol will be displayed correctly in the html files generated from the query help files. ### Academic papers @@ -107,11 +107,11 @@ For example: ### Referencing potential security weaknesses -If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the qhelp file. +If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the query help file. ## Query help example -The following example is a qhelp file for a query from the standard query suite for Java: +The following example is a query help file for a query from the standard query suite for Java: ``` Date: Wed, 8 Apr 2020 09:33:05 +0100 Subject: [PATCH 361/459] docs: html -> HTML --- docs/query-help-style-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/query-help-style-guide.md b/docs/query-help-style-guide.md index 4010c91dba7..0a8fc658759 100644 --- a/docs/query-help-style-guide.md +++ b/docs/query-help-style-guide.md @@ -86,7 +86,7 @@ For example: >W. C. Wake, _Refactoring Workbook_, pp. 93 – 94, Addison-Wesley Professional, 2004. -Note, & symbols need to be replaced by \&. The symbol will be displayed correctly in the html files generated from the query help files. +Note, & symbols need to be replaced by \&. The symbol will be displayed correctly in the HTML files generated from the query help files. ### Academic papers From 7bf0d3d10a965e2813c70586630222839ad8bc9c Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 8 Apr 2020 09:38:18 +0100 Subject: [PATCH 362/459] Update docs/language/learn-ql/writing-queries/introduction-to-queries.rst Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- .../learn-ql/writing-queries/introduction-to-queries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index 43d5e36ffbb..fc17a2e8d36 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -131,7 +131,7 @@ Select clauses for metric queries (``@kind metric``) consist of two 'columns', w Viewing the standard CodeQL queries *********************************** -One of the easiest ways to get started writing your own queries is to modify an existing query. To view the standard CodeQL queries, or to try out other examples, visit the `CodeQL `__ and `CodeQL for Go `__ repositories on GitHub. +One of the easiest ways to get started writing your own queries is to modify an existing query. To view the standard CodeQL queries, or to try out other examples, visit the `CodeQL `__ and `CodeQL for Go `__ repositories on GitHub. You can also find examples of queries developed to find security vulnerabilities and bugs in open source software projects on the `GitHub Security Lab website `__ and in the associated `repository `__. From 6ca865355139bd3e31d22549b1673a3f4d42bcf1 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 8 Apr 2020 09:49:56 +0100 Subject: [PATCH 363/459] Apply suggestions from code review Co-Authored-By: Felicity Chapman --- docs/query-help-style-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/query-help-style-guide.md b/docs/query-help-style-guide.md index 0a8fc658759..c56cd885fce 100644 --- a/docs/query-help-style-guide.md +++ b/docs/query-help-style-guide.md @@ -16,7 +16,7 @@ Query help files must have the same base name as the query they describe and mus ### File structure and layout -Query files are written using a custom XML format, and stored in a file with a `.qhelp` extension. The basic structure is as follows: +Query help files are written using a custom XML format, and stored in a file with a `.qhelp` extension. The basic structure is as follows: ``` @@ -107,7 +107,7 @@ For example: ### Referencing potential security weaknesses -If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the query help file. +If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the output HTML file. ## Query help example @@ -179,4 +179,4 @@ tab width settings cannot be taken into account. -``` \ No newline at end of file +``` From 171b131eb16820818a6b28276cb4e25602090ef6 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 8 Apr 2020 10:23:47 +0100 Subject: [PATCH 364/459] JS: Add test for SourceNode not depending on flowsTo --- .../SourceNodeFlowsTo.expected | 1 + .../RecursionPrevention/SourceNodeFlowsTo.ql | 19 +++++++++++++++++++ .../library-tests/RecursionPrevention/tst.js | 2 ++ 3 files changed, 22 insertions(+) create mode 100644 javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.expected create mode 100644 javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql create mode 100644 javascript/ql/test/library-tests/RecursionPrevention/tst.js diff --git a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.expected b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.expected new file mode 100644 index 00000000000..59f6fd6e79b --- /dev/null +++ b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.expected @@ -0,0 +1 @@ +| Success | diff --git a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql new file mode 100644 index 00000000000..2bc3990c1e7 --- /dev/null +++ b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql @@ -0,0 +1,19 @@ +/** + * Test that fails to compile if the domain of `SourceNode` depends on `SourceNode.flowsTo` (recursively). + * + * This tests adds a negative dependency `flowsTo --!--> SourceNode` + * so that the undesired edge `SourceNode --> flowsTo` completes a negative cycle. + */ +import javascript + +class BadSourceNode extends DataFlow::SourceNode { + BadSourceNode() { + this.(DataFlow::PropRead).getPropertyName() = "foo" + } + + override predicate flowsTo(DataFlow::Node node) { + not node instanceof DataFlow::SourceNode + } +} + +select "Success" diff --git a/javascript/ql/test/library-tests/RecursionPrevention/tst.js b/javascript/ql/test/library-tests/RecursionPrevention/tst.js new file mode 100644 index 00000000000..d5a82a682bc --- /dev/null +++ b/javascript/ql/test/library-tests/RecursionPrevention/tst.js @@ -0,0 +1,2 @@ +// The contents of this file don't matter +let x = 1; From 4acb9da2cf532d4050c8c0e5dcc99a6ae7dad048 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 8 Apr 2020 10:30:21 +0100 Subject: [PATCH 365/459] Update javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll Co-Authored-By: Esben Sparre Andreasen --- javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll index 510d22dbddd..c7efb210ab7 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll @@ -62,6 +62,7 @@ module LazyCache { result = this.flow() or exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName | + // To avoid recursion, this should not depend on `SourceNode`. variable = getVariable() and base = variable.getAnAccess() and access.getBase() = base and From 4ca3ac5ee9e7c17bd537ecefc113d0ef5297f094 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 8 Apr 2020 10:30:45 +0100 Subject: [PATCH 366/459] JS: Add another warning --- javascript/ql/src/semmle/javascript/AMD.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll index 6d86b4d03a6..799db5e0fb5 100644 --- a/javascript/ql/src/semmle/javascript/AMD.qll +++ b/javascript/ql/src/semmle/javascript/AMD.qll @@ -61,6 +61,7 @@ class AmdModuleDefinition extends CallExpr { } private DataFlow::Node getFactoryNodeInternal() { + // To avoid recursion, this should not depend on `SourceNode`. result = DataFlow::valueNode(getLastArgument()) or result = getFactoryNodeInternal().getAPredecessor() } From dacbc1376ca4e34938e779c027c980f7c45ae5b8 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 8 Apr 2020 10:36:04 +0100 Subject: [PATCH 367/459] Update some out of date information --- cpp/ql/src/Options.qll | 2 +- cpp/ql/src/semmle/code/cpp/Compilation.qll | 4 ++-- cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll | 2 +- docs/language/README.rst | 2 +- docs/language/learn-ql/ql-training.rst | 2 +- docs/language/learn-ql/writing-queries/path-queries.rst | 2 +- docs/language/learn-ql/writing-queries/query-help.rst | 2 +- docs/language/ql-handbook/annotations.rst | 6 +++--- docs/language/ql-handbook/language.rst | 2 +- .../ql-training/slide-snippets/intro-ql-general.rst | 6 +++--- docs/query-help-style-guide.md | 2 +- javascript/documentation/flow-summaries.rst | 4 ++-- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cpp/ql/src/Options.qll b/cpp/ql/src/Options.qll index 353d012e339..3c7e320dff6 100644 --- a/cpp/ql/src/Options.qll +++ b/cpp/ql/src/Options.qll @@ -4,7 +4,7 @@ * * By default they fall back to the reasonable defaults provided in * `DefaultOptions.qll`, but by modifying this file, you can customize - * the standard Semmle analyses to give better results for your project. + * the standard analyses to give better results for your project. */ import cpp diff --git a/cpp/ql/src/semmle/code/cpp/Compilation.qll b/cpp/ql/src/semmle/code/cpp/Compilation.qll index 02d962844c8..c5fdcbed5f9 100644 --- a/cpp/ql/src/semmle/code/cpp/Compilation.qll +++ b/cpp/ql/src/semmle/code/cpp/Compilation.qll @@ -21,9 +21,9 @@ private predicate idOf(@compilation x, int y) = equivalenceRelation(id/2)(x, y) * Three things happen to each file during a compilation: * * 1. The file is compiled by a real compiler, such as gcc or VC. - * 2. The file is parsed by Semmle's C++ front-end. + * 2. The file is parsed by the CodeQL C++ front-end. * 3. The parsed representation is converted to database tables by - * Semmle's extractor. + * the CodeQL extractor. * * This class provides CPU and elapsed time information for steps 2 and 3, * but not for step 1. diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll b/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll index 626e50925f9..2d8b52f8622 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll @@ -1,6 +1,6 @@ /** * DEPRECATED: Recursion through `DataFlow::Configuration` is impossible in - * Semmle Core 1.17 and above. There is no need for this module because it's + * any supported tooling. There is no need for this module because it's * impossible to accidentally depend on recursion through * `DataFlow::Configuration` in current releases. * diff --git a/docs/language/README.rst b/docs/language/README.rst index 48beeed5791..ecc9d4d0c09 100644 --- a/docs/language/README.rst +++ b/docs/language/README.rst @@ -109,7 +109,7 @@ examples, see the `template slide deck `__. There, you can also find the documentation for the CodeQL CLI, the CodeQL extension for Visual Studio Code, and LGTM Enterprise. diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index d0eac290a56..5b014ca72fc 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -32,7 +32,7 @@ We recommend that you download `CodeQL for Visual Studio Code `__, `C# `__, `Java `__, `JavaScript `__, and `Python `__ to see examples of the queries included in the Semmle tools. +- Take a look at the path queries for `C/C++ `__, `C# `__, `Java `__, `JavaScript `__, and `Python `__ to see examples of these queries. - Explore the `query cookbooks `__ to see how to access the basic language elements contained in the CodeQL libraries. - For a full list of resources to help you learn CodeQL, including beginner tutorials and language-specific examples, visit `Learning CodeQL `__. diff --git a/docs/language/learn-ql/writing-queries/query-help.rst b/docs/language/learn-ql/writing-queries/query-help.rst index 0ab52f845a8..76c8c442db9 100644 --- a/docs/language/learn-ql/writing-queries/query-help.rst +++ b/docs/language/learn-ql/writing-queries/query-help.rst @@ -63,7 +63,7 @@ Section-level elements are used to group the information in the help file into s +--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ | ``section`` | ``title`` Title of the section | Any block element | General-purpose section with a heading defined by the ``title`` attribute. | +--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``semmleNotes`` | None | Any block element | Semmle-specific notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | +| ``semmleNotes`` | None | Any block element | Implementation notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | +--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ Block elements diff --git a/docs/language/ql-handbook/annotations.rst b/docs/language/ql-handbook/annotations.rst index 816b5ea5310..9177a4197b6 100644 --- a/docs/language/ql-handbook/annotations.rst +++ b/docs/language/ql-handbook/annotations.rst @@ -249,7 +249,7 @@ Compiler pragmas The following compiler pragmas affect the compilation and optimization of queries. You should avoid using these annotations unless you experience significant performance issues. -Before adding pragmas to your code, contact Semmle to describe the performance problems. +Before adding pragmas to your code, contact GitHub to describe the performance problems. That way we can suggest the best solution for your problem, and take it into account when improving the QL optimizer. @@ -292,7 +292,7 @@ optimization on a predicate. This kind of optimization involves taking information from the context of a predicate :ref:`call ` and pushing it into the body of a predicate. This is usually beneficial, so you shouldn't use the ``pragma[nomagic]`` annotation unless recommended to do so -by Semmle. +by GitHub. Note that ``nomagic`` implies ``noinline``. @@ -303,7 +303,7 @@ The ``pragma[noopt]`` annotation is used to prevent the QL optimizer from optimi predicate, except when it's absolutely necessary for compilation and evaluation to work. This is rarely necessary and you should not use the ``pragma[noopt]`` annotation unless -recommended to do so by Semmle, for example, to help resolve performance issues. +recommended to do so by GitHub, for example, to help resolve performance issues. When you use this annotation, be aware of the following issues: diff --git a/docs/language/ql-handbook/language.rst b/docs/language/ql-handbook/language.rst index 5bb7370d11c..1446e18a4f8 100644 --- a/docs/language/ql-handbook/language.rst +++ b/docs/language/ql-handbook/language.rst @@ -1002,7 +1002,7 @@ For casts between the primitive ``float`` and ``int`` types, the above rule mean Postfix casts ~~~~~~~~~~~~~ -*Available from Semmle 1.9.4 onward.* A postfix cast is a primary expression followed by a dot and then a class or primitive type in parentheses: +A postfix cast is a primary expression followed by a dot and then a class or primitive type in parentheses: :: diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index 2dc64517465..f03c0300e25 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -101,7 +101,7 @@ Analysis overview .. note:: - Semmle’s analysis works by extracting a queryable database from your project. For compiled languages, Semmle’s tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. + CodeQL analysis works by extracting a queryable database from your project. For compiled languages, the tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the CodeQL database so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. @@ -129,7 +129,7 @@ QL is: - All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables. - The language is declarative–the user focuses on stating what they would like to find, and leaves the details of how to evaluate the query to the engine. - - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. - - The database generated by Semmle’s tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. + - The object-oriented layer allows us to develop rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. + - The database generated by the CodeQL tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download CodeQL databases from LGTM.com to query locally, by `running queries in your IDE `__. diff --git a/docs/query-help-style-guide.md b/docs/query-help-style-guide.md index 58e2d93f95e..7ddda7c60de 100644 --- a/docs/query-help-style-guide.md +++ b/docs/query-help-style-guide.md @@ -2,7 +2,7 @@ ## Introduction -When you contribute a new query to Semmle/ql for inclusion in the standard queries, or add a custom query for analysis in LGTM, you should also write a query help file. This file provides detailed information about the purpose and use of the query, which is available to users in LGTM (for example [here](https://lgtm.com/rules/1506093386171/)) and on the query homepages: +When you contribute a new [supported query](supported-queries.md) to this repository, or add a custom query for analysis in LGTM, you should also write a query help file. This file provides detailed information about the purpose and use of the query, which is available to users in LGTM (for example [here](https://lgtm.com/rules/1506093386171/)) and on the query homepages: * [C/C++ queries](https://help.semmle.com/wiki/display/CCPPOBJ/) * [C# queries](https://help.semmle.com/wiki/display/CSHARP/) diff --git a/javascript/documentation/flow-summaries.rst b/javascript/documentation/flow-summaries.rst index edd6cb027b0..6a6c482f69d 100644 --- a/javascript/documentation/flow-summaries.rst +++ b/javascript/documentation/flow-summaries.rst @@ -5,7 +5,7 @@ Overview -------- This document presents an approach for running information flow analyses (such as the standard -Semmle security queries) on an application that depends on one or more npm packages. Instead of +security queries) on an application that depends on one or more npm packages. Instead of installing the npm packages during the snapshot build and analyzing them together with application code, we analyze each package in isolation and compute *flow summaries* that record information about any sources, sinks and flow steps contributed by the package's API. These flow summaries @@ -41,7 +41,7 @@ If the value of ``p`` can be controlled by an untrusted user, this would allow t folders, which may not be desirable. By analyzing the application code base together with the source code for the ``mkdirp`` package, -Semmle's default path injection analysis would be able to track taint through the call to ``mkdirp`` into its +the default path injection analysis would be able to track taint through the call to ``mkdirp`` into its implementation, which ultimately uses built-in Node.js file system APIs to create the folder. Since the path injection analysis has built-in models of these APIs it would then be able to spot and flag this vulnerability. From 92aee59ca5c387b4c035c499a4f943fc45fe23aa Mon Sep 17 00:00:00 2001 From: Shati Patel Date: Wed, 8 Apr 2020 09:56:01 +0100 Subject: [PATCH 368/459] Change "Qhelp" to "Query help" --- .../learn-ql/writing-queries/query-help.rst | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/language/learn-ql/writing-queries/query-help.rst b/docs/language/learn-ql/writing-queries/query-help.rst index 0ab52f845a8..2bfc0db4b7e 100644 --- a/docs/language/learn-ql/writing-queries/query-help.rst +++ b/docs/language/learn-ql/writing-queries/query-help.rst @@ -26,7 +26,7 @@ Each query help file provides detailed information about the purpose and use of Structure ========= -Query help files are written using an XML format called Qhelp (``.qhelp``). Query help files must have the same base name as the query they describe, and must be located in the same directory. The basic structure is as follows: +Query help files are written using a custom XML format, and stored in a file with a ``.qhelp`` extension. Query help files must have the same base name as the query they describe, and must be located in the same directory. The basic structure is as follows: .. code-block:: xml @@ -44,32 +44,32 @@ Section-level elements Section-level elements are used to group the information in the help file into sections. Many sections have a heading, either defined by a ``title`` attribute or a default value. The following section-level elements are optional child elements of the ``qhelp`` element. -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| Element | Attributes | Children | Purpose of section | -+====================+====================================+========================+===============================================================================================================================================+ -| ``example`` | None | Any block element | Demonstrate an example of code that violates the rule implemented by the query with guidance on how to fix it. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``fragment`` | None | Any block element | See :ref:`Qhelp inclusion ` below. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``hr`` | None | None | A horizontal rule. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``include`` | ``src`` The Qhelp file to include. | None | Include a Qhelp file at the location of this element. See :ref:`Qhelp inclusion ` below. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``overview`` | None | Any block element | Overview of the purpose of the query. Typically this is the first section in a query document. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``recommendation`` | None | Any block element | Recommend how to address any alerts that this query identifies. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``references`` | None | ``li`` elements | Reference list. Typically this is the last section in a query document. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``section`` | ``title`` Title of the section | Any block element | General-purpose section with a heading defined by the ``title`` attribute. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``semmleNotes`` | None | Any block element | Semmle-specific notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| Element | Attributes | Children | Purpose of section | ++====================+=========================================+========================+===============================================================================================================================================+ +| ``example`` | None | Any block element | Demonstrate an example of code that violates the rule implemented by the query with guidance on how to fix it. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``fragment`` | None | Any block element | See :ref:`Query help inclusion ` below. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``hr`` | None | None | A horizontal rule. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``include`` | ``src`` The query help file to include. | None | Include a query help file at the location of this element. See :ref:`Query help inclusion ` below. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``overview`` | None | Any block element | Overview of the purpose of the query. Typically this is the first section in a query document. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``recommendation`` | None | Any block element | Recommend how to address any alerts that this query identifies. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``references`` | None | ``li`` elements | Reference list. Typically this is the last section in a query document. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``section`` | ``title`` Title of the section | Any block element | General-purpose section with a heading defined by the ``title`` attribute. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``semmleNotes`` | None | Any block element | Semmle-specific notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ Block elements ============== -The following elements are optional child elements of the ``section``, ``example``, ``fragment``, ``recommendation``, ``overview`` and ``semmleNotes`` elements. +The following elements are optional child elements of the ``section``, ``example``, ``fragment``, ``recommendation``, ``overview``, and ``semmleNotes`` elements. .. table:: :widths: 7 20 10 25 @@ -84,7 +84,7 @@ The following elements are optional child elements of the ``section``, ``example | | | ``height`` Optional, height of the image. | | | | | | ``width`` Optional, the width of the image. | | | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | ``include`` | ``src`` The Qhelp file to include. | None | Include a Qhelp file at the location of this element. See :ref:`Qhelp inclusion ` below for more information. | + | ``include`` | ``src`` The query help file to include. | None | Include a query help file at the location of this element. See :ref:`Query help inclusion ` below for more information. | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``ol`` | None | ``li`` | Display an ordered list. See List elements below. | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -105,12 +105,12 @@ The following elements are optional child elements of the ``section``, ``example List elements ============= -Qhelp files support two types of block elements for lists: ``ul`` and ``ol``. Both block elements support only one child elements of the type ``li``. Each ``li`` element contains either inline content or a block element. +Query help files support two types of block elements for lists: ``ul`` and ``ol``. Both block elements support only one child elements of the type ``li``. Each ``li`` element contains either inline content or a block element. Table elements ============== -The ``table`` block element is used to include a table in a Qhelp file. Each table includes a number of rows, each of which includes a number of cells. The data in the cells will be rendered as a grid. +The ``table`` block element is used to include a table in a query help file. Each table includes a number of rows, each of which includes a number of cells. The data in the cells will be rendered as a grid. +-----------+------------+--------------------+-------------------------------------------+ | Element | Attributes | Children | Purpose | @@ -159,12 +159,12 @@ Inline content is used to define the content for paragraphs, list items, table c .. _qhelp-inclusion: -Qhelp inclusion -=============== +Query help inclusion +==================== -To enable the reuse of content between different help topics, shared content can be stored in one Qhelp file and then included in a number of other Qhelp files using the ``include`` element. The shared content can stored either in the same directory as the including files, or in ``SEMMLE_DIST/docs/include``. +To reuse content between different help topics, you can store shared content in one query help file and then include it in a number of other query help files using the ``include`` element. The shared content can be stored either in the same directory as the including files, or in ``SEMMLE_DIST/docs/include``. -The ``include`` element can be used as a section or block element, the content of the Qhelp file defined by the ``src`` attribute must contain elements that are appropriate to the location of the ``include`` element. +The ``include`` element can be used as a section or block element. The content of the query help file defined by the ``src`` attribute must contain elements that are appropriate to the location of the ``include`` element. Section-level include elements ------------------------------ @@ -177,7 +177,7 @@ Section-level ``include`` elements can be located beneath the top-level ``qhelp` -In this example, the `XSS.qhelp `__ file must conform to the standard for a full Qhelp file as described above. That is, the ``qhelp`` element may only contain non-``fragment``, section-level elements. +In this example, the `XSS.qhelp `__ file must conform to the standard for a full query help file as described above. That is, the ``qhelp`` element may only contain non-``fragment``, section-level elements. Block-level include elements ---------------------------- From df1b45024892043ab818c4e3401463eb1f213100 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 8 Apr 2020 11:25:36 +0100 Subject: [PATCH 369/459] Update writing-queries.rst --- docs/language/learn-ql/writing-queries/writing-queries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/writing-queries/writing-queries.rst b/docs/language/learn-ql/writing-queries/writing-queries.rst index 937ab6efde9..bdf702ded1c 100644 --- a/docs/language/learn-ql/writing-queries/writing-queries.rst +++ b/docs/language/learn-ql/writing-queries/writing-queries.rst @@ -22,4 +22,4 @@ CodeQL queries are used in code scanning analyses to find problems in source cod - :doc:`Providing locations in CodeQL queries <../locations>`: CodeQL includes mechanisms for extracting the location of elements in a codebase. Use these mechanisms when writing custom CodeQL queries and libraries to help display information to users. - :doc:`About data flow analysis <../intro-to-data-flow>`: Data flow analysis is used to compute the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used. - :doc:`Creating path queries `: You can create path queries to visualize the flow of information through a codebase. -- :doc:`trouble shooting query performance `: Improve the performance of your CodeQL queries by following a few simple guidelines. +- :doc:`Troubleshooting query performance `: Improve the performance of your CodeQL queries by following a few simple guidelines. From 9db6b8f1e2b63c1602ae6dcfe3d0aedaf01cf728 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 8 Apr 2020 11:42:30 +0100 Subject: [PATCH 370/459] Update docs/language/learn-ql/writing-queries/query-help.rst Co-Authored-By: James Fletcher <42464962+jf205@users.noreply.github.com> --- docs/language/learn-ql/writing-queries/query-help.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/writing-queries/query-help.rst b/docs/language/learn-ql/writing-queries/query-help.rst index 76c8c442db9..44ef01cccf7 100644 --- a/docs/language/learn-ql/writing-queries/query-help.rst +++ b/docs/language/learn-ql/writing-queries/query-help.rst @@ -63,7 +63,7 @@ Section-level elements are used to group the information in the help file into s +--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ | ``section`` | ``title`` Title of the section | Any block element | General-purpose section with a heading defined by the ``title`` attribute. | +--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``semmleNotes`` | None | Any block element | Implementation notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | +| ``semmleNotes`` | None | Any block element | Implementation notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | +--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ Block elements From 6a1b11f9d1cf18691d3fac9e7e26e104e3d66a46 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 8 Apr 2020 11:59:40 +0100 Subject: [PATCH 371/459] docs: further updates to learn-codeql project --- docs/language/learn-ql/cpp/ql-for-cpp.rst | 6 ++++++ docs/language/learn-ql/java/ql-for-java.rst | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/cpp/ql-for-cpp.rst b/docs/language/learn-ql/cpp/ql-for-cpp.rst index 8961c3ef80a..b04c7cc3a88 100644 --- a/docs/language/learn-ql/cpp/ql-for-cpp.rst +++ b/docs/language/learn-ql/cpp/ql-for-cpp.rst @@ -34,6 +34,12 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Detecting a potential buffer overflow `: You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. +- :doc:`Using range analysis for C and C++ `: You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow. + +- :doc:`Hash consing and value numbering `: You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases. + +- :doc:`Using the guards library in C and C++ `: You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases. + Further reading --------------- diff --git a/docs/language/learn-ql/java/ql-for-java.rst b/docs/language/learn-ql/java/ql-for-java.rst index fccaecca247..a3c9cd79d71 100644 --- a/docs/language/learn-ql/java/ql-for-java.rst +++ b/docs/language/learn-ql/java/ql-for-java.rst @@ -18,7 +18,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - `Basic Java query `__: Learn to write and run a simple CodeQL query using LGTM. -- :doc:`CodeQL library for Java `: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++. +- :doc:`CodeQL library for Java `: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for Java. - :doc:`Analyzing data flow in Java `: You can use CodeQL to track the flow of data through a Java program to its use. @@ -34,7 +34,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Working with source locations `: You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. -- :doc:`lasses for working with Java code `: CodeQL has a large selection of classes for working with Java statements and expressions. +- :doc:`Classes for working with Java code `: CodeQL has a large selection of classes for working with Java statements and expressions. Further reading From e4e0d3b573f0047e817d8bac15309e469ae035a1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 8 Apr 2020 13:00:51 +0200 Subject: [PATCH 372/459] C++: Add test cases showing that static member function calls get 'this' pointers and side effects for 'this' when accessed through qualifiers --- .../library-tests/ir/ir/PrintAST.expected | 205 ++++++++++++++++++ cpp/ql/test/library-tests/ir/ir/ir.cpp | 31 +++ .../test/library-tests/ir/ir/raw_ir.expected | 162 ++++++++++++++ 3 files changed, 398 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index f6d9fdc8a35..e218b6daf47 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -4048,6 +4048,27 @@ ir.cpp: #-----| Type = [RValueReferenceType] C && # 628| [Destructor] void C::~C() # 628| params: +#-----| body: [Block] { ... } +#-----| 0: [ReturnStmt] return ... +# 628| destructions: +# 628| 0: [DestructorFieldDestruction] destructor field destruction of m_f +# 628| Type = [Struct] String +# 628| ValueCategory = prvalue +# 628| 0: [DestructorCall] call to ~String +# 628| Type = [VoidType] void +# 628| ValueCategory = prvalue +# 628| -1: [ImplicitThisFieldAccess] m_f +# 628| Type = [Struct] String +# 628| ValueCategory = lvalue +# 628| 1: [DestructorFieldDestruction] destructor field destruction of m_b +# 628| Type = [Struct] String +# 628| ValueCategory = prvalue +# 628| 0: [DestructorCall] call to ~String +# 628| Type = [VoidType] void +# 628| ValueCategory = prvalue +# 628| -1: [ImplicitThisFieldAccess] m_b +# 628| Type = [Struct] String +# 628| ValueCategory = lvalue # 630| [MemberFunction] int C::StaticMemberFunction(int) # 630| params: # 630| 0: [Parameter] x @@ -8545,6 +8566,190 @@ ir.cpp: # 1255| Type = [CharPointerType] char * # 1255| ValueCategory = prvalue(load) # 1256| 3: [ReturnStmt] return ... +# 1258| [CopyAssignmentOperator] A& A::operator=(A const&) +# 1258| params: +#-----| 0: [Parameter] p#0 +#-----| Type = [LValueReferenceType] const A & +# 1258| [MoveAssignmentOperator] A& A::operator=(A&&) +# 1258| params: +#-----| 0: [Parameter] p#0 +#-----| Type = [RValueReferenceType] A && +# 1261| [MemberFunction] void A::static_member(A*, int) +# 1261| params: +# 1261| 0: [Parameter] a +# 1261| Type = [PointerType] A * +# 1261| 1: [Parameter] x +# 1261| Type = [IntType] int +# 1261| body: [Block] { ... } +# 1262| 0: [ExprStmt] ExprStmt +# 1262| 0: [AssignExpr] ... = ... +# 1262| Type = [IntType] int +# 1262| ValueCategory = lvalue +# 1262| 0: [PointerFieldAccess] member +# 1262| Type = [IntType] int +# 1262| ValueCategory = lvalue +# 1262| -1: [VariableAccess] a +# 1262| Type = [PointerType] A * +# 1262| ValueCategory = prvalue(load) +# 1262| 1: [VariableAccess] x +# 1262| Type = [IntType] int +# 1262| ValueCategory = prvalue(load) +# 1263| 1: [ReturnStmt] return ... +# 1265| [MemberFunction] void A::static_member_without_def() +# 1265| params: +# 1268| [TopLevelFunction] A* getAnInstanceOfA() +# 1268| params: +# 1270| [TopLevelFunction] void test_static_member_functions(int, A*) +# 1270| params: +# 1270| 0: [Parameter] int_arg +# 1270| Type = [IntType] int +# 1270| 1: [Parameter] a_arg +# 1270| Type = [PointerType] A * +# 1270| body: [Block] { ... } +# 1271| 0: [DeclStmt] declaration +# 1271| 0: [VariableDeclarationEntry] definition of c +# 1271| Type = [Class] C +# 1271| init: [Initializer] initializer for c +# 1271| expr: [ConstructorCall] call to C +# 1271| Type = [VoidType] void +# 1271| ValueCategory = prvalue +# 1272| 1: [ExprStmt] ExprStmt +# 1272| 0: [FunctionCall] call to StaticMemberFunction +# 1272| Type = [IntType] int +# 1272| ValueCategory = prvalue +# 1272| -1: [VariableAccess] c +# 1272| Type = [Class] C +# 1272| ValueCategory = lvalue +# 1272| 0: [Literal] 10 +# 1272| Type = [IntType] int +# 1272| Value = [Literal] 10 +# 1272| ValueCategory = prvalue +# 1273| 2: [ExprStmt] ExprStmt +# 1273| 0: [FunctionCall] call to StaticMemberFunction +# 1273| Type = [IntType] int +# 1273| ValueCategory = prvalue +# 1273| 0: [Literal] 10 +# 1273| Type = [IntType] int +# 1273| Value = [Literal] 10 +# 1273| ValueCategory = prvalue +# 1275| 3: [DeclStmt] declaration +# 1275| 0: [VariableDeclarationEntry] definition of a +# 1275| Type = [Struct] A +# 1276| 4: [ExprStmt] ExprStmt +# 1276| 0: [FunctionCall] call to static_member +# 1276| Type = [VoidType] void +# 1276| ValueCategory = prvalue +# 1276| -1: [VariableAccess] a +# 1276| Type = [Struct] A +# 1276| ValueCategory = lvalue +# 1276| 0: [AddressOfExpr] & ... +# 1276| Type = [PointerType] A * +# 1276| ValueCategory = prvalue +# 1276| 0: [VariableAccess] a +# 1276| Type = [Struct] A +# 1276| ValueCategory = lvalue +# 1276| 1: [VariableAccess] int_arg +# 1276| Type = [IntType] int +# 1276| ValueCategory = prvalue(load) +# 1277| 5: [ExprStmt] ExprStmt +# 1277| 0: [FunctionCall] call to static_member +# 1277| Type = [VoidType] void +# 1277| ValueCategory = prvalue +# 1277| 0: [AddressOfExpr] & ... +# 1277| Type = [PointerType] A * +# 1277| ValueCategory = prvalue +# 1277| 0: [VariableAccess] a +# 1277| Type = [Struct] A +# 1277| ValueCategory = lvalue +# 1277| 1: [VariableAccess] int_arg +# 1277| Type = [IntType] int +# 1277| ValueCategory = prvalue(load) +# 1279| 6: [ExprStmt] ExprStmt +# 1279| 0: [FunctionCall] call to static_member +# 1279| Type = [VoidType] void +# 1279| ValueCategory = prvalue +# 1279| -1: [ParenthesisExpr] (...) +# 1279| Type = [PointerType] A * +# 1279| ValueCategory = prvalue +# 1279| expr: [AddressOfExpr] & ... +# 1279| Type = [PointerType] A * +# 1279| ValueCategory = prvalue +# 1279| 0: [VariableAccess] a +# 1279| Type = [Struct] A +# 1279| ValueCategory = lvalue +# 1279| 0: [VariableAccess] a_arg +# 1279| Type = [PointerType] A * +# 1279| ValueCategory = prvalue(load) +# 1279| 1: [AddExpr] ... + ... +# 1279| Type = [IntType] int +# 1279| ValueCategory = prvalue +# 1279| 0: [VariableAccess] int_arg +# 1279| Type = [IntType] int +# 1279| ValueCategory = prvalue(load) +# 1279| 1: [Literal] 2 +# 1279| Type = [IntType] int +# 1279| Value = [Literal] 2 +# 1279| ValueCategory = prvalue +# 1280| 7: [ExprStmt] ExprStmt +# 1280| 0: [FunctionCall] call to static_member +# 1280| Type = [VoidType] void +# 1280| ValueCategory = prvalue +# 1280| -1: [ParenthesisExpr] (...) +# 1280| Type = [Struct] A +# 1280| ValueCategory = lvalue +# 1280| expr: [PointerDereferenceExpr] * ... +# 1280| Type = [Struct] A +# 1280| ValueCategory = lvalue +# 1280| 0: [VariableAccess] a_arg +# 1280| Type = [PointerType] A * +# 1280| ValueCategory = prvalue(load) +# 1280| 0: [AddressOfExpr] & ... +# 1280| Type = [PointerType] A * +# 1280| ValueCategory = prvalue +# 1280| 0: [VariableAccess] a +# 1280| Type = [Struct] A +# 1280| ValueCategory = lvalue +# 1280| 1: [Literal] 99 +# 1280| Type = [IntType] int +# 1280| Value = [Literal] 99 +# 1280| ValueCategory = prvalue +# 1281| 8: [ExprStmt] ExprStmt +# 1281| 0: [FunctionCall] call to static_member +# 1281| Type = [VoidType] void +# 1281| ValueCategory = prvalue +# 1281| -1: [VariableAccess] a_arg +# 1281| Type = [PointerType] A * +# 1281| ValueCategory = prvalue(load) +# 1281| 0: [VariableAccess] a_arg +# 1281| Type = [PointerType] A * +# 1281| ValueCategory = prvalue(load) +# 1281| 1: [UnaryMinusExpr] - ... +# 1281| Type = [IntType] int +# 1281| Value = [UnaryMinusExpr] -1 +# 1281| ValueCategory = prvalue +# 1281| 0: [Literal] 1 +# 1281| Type = [IntType] int +# 1281| Value = [Literal] 1 +# 1281| ValueCategory = prvalue +# 1283| 9: [ExprStmt] ExprStmt +# 1283| 0: [FunctionCall] call to static_member_without_def +# 1283| Type = [VoidType] void +# 1283| ValueCategory = prvalue +# 1283| -1: [VariableAccess] a +# 1283| Type = [Struct] A +# 1283| ValueCategory = lvalue +# 1284| 10: [ExprStmt] ExprStmt +# 1284| 0: [FunctionCall] call to static_member_without_def +# 1284| Type = [VoidType] void +# 1284| ValueCategory = prvalue +# 1286| 11: [ExprStmt] ExprStmt +# 1286| 0: [FunctionCall] call to static_member_without_def +# 1286| Type = [VoidType] void +# 1286| ValueCategory = prvalue +# 1286| -1: [FunctionCall] call to getAnInstanceOfA +# 1286| Type = [PointerType] A * +# 1286| ValueCategory = prvalue +# 1287| 12: [ReturnStmt] return ... perf-regression.cpp: # 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&) # 4| params: diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index 6f6ab081347..ec40d944789 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1255,4 +1255,35 @@ void test_strings(char *s1, char *s2) { strcat(buffer, s2); } +struct A { + int member; + + static void static_member(A* a, int x) { + a->member = x; + } + + static void static_member_without_def(); +}; + +A* getAnInstanceOfA(); + +void test_static_member_functions(int int_arg, A* a_arg) { + C c; + c.StaticMemberFunction(10); + C::StaticMemberFunction(10); + + A a; + a.static_member(&a, int_arg); + A::static_member(&a, int_arg); + + (&a)->static_member(a_arg, int_arg + 2); + (*a_arg).static_member(&a, 99); + a_arg->static_member(a_arg, -1); + + a.static_member_without_def(); + A::static_member_without_def(); + + getAnInstanceOfA()->static_member_without_def(); +} + // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 28e6de0e1f1..a50c9e1535d 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2991,6 +2991,27 @@ ir.cpp: # 622| v622_19(void) = AliasedUse : ~mu622_4 # 622| v622_20(void) = ExitFunction : +# 628| void C::~C() +# 628| Block 0 +# 628| v628_1(void) = EnterFunction : +# 628| mu628_2(unknown) = AliasedDefinition : +# 628| mu628_3(unknown) = InitializeNonLocal : +# 628| mu628_4(unknown) = UnmodeledDefinition : +# 628| r628_5(glval) = InitializeThis : +#-----| v0_1(void) = NoOp : +# 628| r628_6(glval) = FieldAddress[m_f] : r628_5 +# 628| r628_7(glval) = FunctionAddress[~String] : +# 628| v628_8(void) = Call : func:r628_7, this:r628_6 +# 628| mu628_9(unknown) = ^CallSideEffect : ~mu628_4 +# 628| r628_10(glval) = FieldAddress[m_b] : r628_5 +# 628| r628_11(glval) = FunctionAddress[~String] : +# 628| v628_12(void) = Call : func:r628_11, this:r628_10 +# 628| mu628_13(unknown) = ^CallSideEffect : ~mu628_4 +# 628| v628_14(void) = ReturnVoid : +# 628| v628_15(void) = UnmodeledUse : mu* +# 628| v628_16(void) = AliasedUse : ~mu628_4 +# 628| v628_17(void) = ExitFunction : + # 630| int C::StaticMemberFunction(int) # 630| Block 0 # 630| v630_1(void) = EnterFunction : @@ -6483,6 +6504,147 @@ ir.cpp: # 1251| v1251_17(void) = AliasedUse : ~mu1251_4 # 1251| v1251_18(void) = ExitFunction : +# 1261| void A::static_member(A*, int) +# 1261| Block 0 +# 1261| v1261_1(void) = EnterFunction : +# 1261| mu1261_2(unknown) = AliasedDefinition : +# 1261| mu1261_3(unknown) = InitializeNonLocal : +# 1261| mu1261_4(unknown) = UnmodeledDefinition : +# 1261| r1261_5(glval) = VariableAddress[a] : +# 1261| mu1261_6(A *) = InitializeParameter[a] : &:r1261_5 +# 1261| r1261_7(A *) = Load : &:r1261_5, ~mu1261_6 +# 1261| mu1261_8(unknown) = InitializeIndirection[a] : &:r1261_7 +# 1261| r1261_9(glval) = VariableAddress[x] : +# 1261| mu1261_10(int) = InitializeParameter[x] : &:r1261_9 +# 1262| r1262_1(glval) = VariableAddress[x] : +# 1262| r1262_2(int) = Load : &:r1262_1, ~mu1261_4 +# 1262| r1262_3(glval) = VariableAddress[a] : +# 1262| r1262_4(A *) = Load : &:r1262_3, ~mu1261_4 +# 1262| r1262_5(glval) = FieldAddress[member] : r1262_4 +# 1262| mu1262_6(int) = Store : &:r1262_5, r1262_2 +# 1263| v1263_1(void) = NoOp : +# 1261| v1261_11(void) = ReturnIndirection : &:r1261_7, ~mu1261_4 +# 1261| v1261_12(void) = ReturnVoid : +# 1261| v1261_13(void) = UnmodeledUse : mu* +# 1261| v1261_14(void) = AliasedUse : ~mu1261_4 +# 1261| v1261_15(void) = ExitFunction : + +# 1270| void test_static_member_functions(int, A*) +# 1270| Block 0 +# 1270| v1270_1(void) = EnterFunction : +# 1270| mu1270_2(unknown) = AliasedDefinition : +# 1270| mu1270_3(unknown) = InitializeNonLocal : +# 1270| mu1270_4(unknown) = UnmodeledDefinition : +# 1270| r1270_5(glval) = VariableAddress[int_arg] : +# 1270| mu1270_6(int) = InitializeParameter[int_arg] : &:r1270_5 +# 1270| r1270_7(glval) = VariableAddress[a_arg] : +# 1270| mu1270_8(A *) = InitializeParameter[a_arg] : &:r1270_7 +# 1270| r1270_9(A *) = Load : &:r1270_7, ~mu1270_8 +# 1270| mu1270_10(unknown) = InitializeIndirection[a_arg] : &:r1270_9 +# 1271| r1271_1(glval) = VariableAddress[c] : +# 1271| mu1271_2(C) = Uninitialized[c] : &:r1271_1 +# 1271| r1271_3(glval) = FunctionAddress[C] : +# 1271| v1271_4(void) = Call : func:r1271_3, this:r1271_1 +# 1271| mu1271_5(unknown) = ^CallSideEffect : ~mu1270_4 +# 1271| mu1271_6(C) = ^IndirectMayWriteSideEffect[-1] : &:r1271_1 +# 1272| r1272_1(glval) = VariableAddress[c] : +# 1272| r1272_2(glval) = FunctionAddress[StaticMemberFunction] : +# 1272| r1272_3(int) = Constant[10] : +# 1272| r1272_4(int) = Call : func:r1272_2, this:r1272_1, 0:r1272_3 +# 1272| mu1272_5(unknown) = ^CallSideEffect : ~mu1270_4 +# 1272| v1272_6(void) = ^BufferReadSideEffect[-1] : &:r1272_1, ~mu1270_4 +# 1272| mu1272_7(C) = ^IndirectMayWriteSideEffect[-1] : &:r1272_1 +# 1273| r1273_1(glval) = FunctionAddress[StaticMemberFunction] : +# 1273| r1273_2(int) = Constant[10] : +# 1273| r1273_3(int) = Call : func:r1273_1, 0:r1273_2 +# 1273| mu1273_4(unknown) = ^CallSideEffect : ~mu1270_4 +# 1275| r1275_1(glval) = VariableAddress[a] : +# 1275| mu1275_2(A) = Uninitialized[a] : &:r1275_1 +# 1276| r1276_1(glval) = VariableAddress[a] : +# 1276| r1276_2(glval) = FunctionAddress[static_member] : +# 1276| r1276_3(glval) = VariableAddress[a] : +# 1276| r1276_4(A *) = CopyValue : r1276_3 +# 1276| r1276_5(glval) = VariableAddress[int_arg] : +# 1276| r1276_6(int) = Load : &:r1276_5, ~mu1270_4 +# 1276| v1276_7(void) = Call : func:r1276_2, this:r1276_1, 0:r1276_4, 1:r1276_6 +# 1276| mu1276_8(unknown) = ^CallSideEffect : ~mu1270_4 +# 1276| v1276_9(void) = ^BufferReadSideEffect[-1] : &:r1276_1, ~mu1270_4 +# 1276| v1276_10(void) = ^BufferReadSideEffect[0] : &:r1276_4, ~mu1270_4 +# 1276| mu1276_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r1276_1 +# 1276| mu1276_12(unknown) = ^BufferMayWriteSideEffect[0] : &:r1276_4 +# 1277| r1277_1(glval) = FunctionAddress[static_member] : +# 1277| r1277_2(glval) = VariableAddress[a] : +# 1277| r1277_3(A *) = CopyValue : r1277_2 +# 1277| r1277_4(glval) = VariableAddress[int_arg] : +# 1277| r1277_5(int) = Load : &:r1277_4, ~mu1270_4 +# 1277| v1277_6(void) = Call : func:r1277_1, 0:r1277_3, 1:r1277_5 +# 1277| mu1277_7(unknown) = ^CallSideEffect : ~mu1270_4 +# 1277| v1277_8(void) = ^BufferReadSideEffect[0] : &:r1277_3, ~mu1270_4 +# 1277| mu1277_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r1277_3 +# 1279| r1279_1(glval) = VariableAddress[a] : +# 1279| r1279_2(A *) = CopyValue : r1279_1 +# 1279| r1279_3(glval) = FunctionAddress[static_member] : +# 1279| r1279_4(glval) = VariableAddress[a_arg] : +# 1279| r1279_5(A *) = Load : &:r1279_4, ~mu1270_4 +# 1279| r1279_6(glval) = VariableAddress[int_arg] : +# 1279| r1279_7(int) = Load : &:r1279_6, ~mu1270_4 +# 1279| r1279_8(int) = Constant[2] : +# 1279| r1279_9(int) = Add : r1279_7, r1279_8 +# 1279| v1279_10(void) = Call : func:r1279_3, this:r1279_2, 0:r1279_5, 1:r1279_9 +# 1279| mu1279_11(unknown) = ^CallSideEffect : ~mu1270_4 +# 1279| v1279_12(void) = ^BufferReadSideEffect[-1] : &:r1279_2, ~mu1270_4 +# 1279| v1279_13(void) = ^BufferReadSideEffect[0] : &:r1279_5, ~mu1270_4 +# 1279| mu1279_14(A) = ^IndirectMayWriteSideEffect[-1] : &:r1279_2 +# 1279| mu1279_15(unknown) = ^BufferMayWriteSideEffect[0] : &:r1279_5 +# 1280| r1280_1(glval) = VariableAddress[a_arg] : +# 1280| r1280_2(A *) = Load : &:r1280_1, ~mu1270_4 +# 1280| r1280_3(glval) = CopyValue : r1280_2 +# 1280| r1280_4(glval) = FunctionAddress[static_member] : +# 1280| r1280_5(glval) = VariableAddress[a] : +# 1280| r1280_6(A *) = CopyValue : r1280_5 +# 1280| r1280_7(int) = Constant[99] : +# 1280| v1280_8(void) = Call : func:r1280_4, this:r1280_3, 0:r1280_6, 1:r1280_7 +# 1280| mu1280_9(unknown) = ^CallSideEffect : ~mu1270_4 +# 1280| v1280_10(void) = ^BufferReadSideEffect[-1] : &:r1280_3, ~mu1270_4 +# 1280| v1280_11(void) = ^BufferReadSideEffect[0] : &:r1280_6, ~mu1270_4 +# 1280| mu1280_12(A) = ^IndirectMayWriteSideEffect[-1] : &:r1280_3 +# 1280| mu1280_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r1280_6 +# 1281| r1281_1(glval) = VariableAddress[a_arg] : +# 1281| r1281_2(A *) = Load : &:r1281_1, ~mu1270_4 +# 1281| r1281_3(glval) = FunctionAddress[static_member] : +# 1281| r1281_4(glval) = VariableAddress[a_arg] : +# 1281| r1281_5(A *) = Load : &:r1281_4, ~mu1270_4 +# 1281| r1281_6(int) = Constant[-1] : +# 1281| v1281_7(void) = Call : func:r1281_3, this:r1281_2, 0:r1281_5, 1:r1281_6 +# 1281| mu1281_8(unknown) = ^CallSideEffect : ~mu1270_4 +# 1281| v1281_9(void) = ^BufferReadSideEffect[-1] : &:r1281_2, ~mu1270_4 +# 1281| v1281_10(void) = ^BufferReadSideEffect[0] : &:r1281_5, ~mu1270_4 +# 1281| mu1281_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r1281_2 +# 1281| mu1281_12(unknown) = ^BufferMayWriteSideEffect[0] : &:r1281_5 +# 1283| r1283_1(glval) = VariableAddress[a] : +# 1283| r1283_2(glval) = FunctionAddress[static_member_without_def] : +# 1283| v1283_3(void) = Call : func:r1283_2, this:r1283_1 +# 1283| mu1283_4(unknown) = ^CallSideEffect : ~mu1270_4 +# 1283| v1283_5(void) = ^BufferReadSideEffect[-1] : &:r1283_1, ~mu1270_4 +# 1283| mu1283_6(A) = ^IndirectMayWriteSideEffect[-1] : &:r1283_1 +# 1284| r1284_1(glval) = FunctionAddress[static_member_without_def] : +# 1284| v1284_2(void) = Call : func:r1284_1 +# 1284| mu1284_3(unknown) = ^CallSideEffect : ~mu1270_4 +# 1286| r1286_1(glval) = FunctionAddress[getAnInstanceOfA] : +# 1286| r1286_2(A *) = Call : func:r1286_1 +# 1286| mu1286_3(unknown) = ^CallSideEffect : ~mu1270_4 +# 1286| r1286_4(glval) = FunctionAddress[static_member_without_def] : +# 1286| v1286_5(void) = Call : func:r1286_4, this:r1286_2 +# 1286| mu1286_6(unknown) = ^CallSideEffect : ~mu1270_4 +# 1286| v1286_7(void) = ^BufferReadSideEffect[-1] : &:r1286_2, ~mu1270_4 +# 1286| mu1286_8(A) = ^IndirectMayWriteSideEffect[-1] : &:r1286_2 +# 1287| v1287_1(void) = NoOp : +# 1270| v1270_11(void) = ReturnIndirection : &:r1270_9, ~mu1270_4 +# 1270| v1270_12(void) = ReturnVoid : +# 1270| v1270_13(void) = UnmodeledUse : mu* +# 1270| v1270_14(void) = AliasedUse : ~mu1270_4 +# 1270| v1270_15(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0 From 07d913125691f9386d85ece5db547f10f1258717 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 8 Apr 2020 12:14:40 +0100 Subject: [PATCH 373/459] Update docs/language/learn-ql/writing-queries/query-help.rst Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/writing-queries/query-help.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/language/learn-ql/writing-queries/query-help.rst b/docs/language/learn-ql/writing-queries/query-help.rst index 8795569d5bc..89cad6528c6 100644 --- a/docs/language/learn-ql/writing-queries/query-help.rst +++ b/docs/language/learn-ql/writing-queries/query-help.rst @@ -84,8 +84,7 @@ The following elements are optional child elements of the ``section``, ``example | | | ``height`` Optional, height of the image. | | | | | | ``width`` Optional, the width of the image. | | | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | ``include`` | ``src`` The query help file to include. | None | Include a query help file at the location of this element. See :ref:`Query help inclusion < - -inclusion>` below for more information. | + | ``include`` | ``src`` The query help file to include. | None | Include a query help file at the location of this element. See :ref:`Query help inclusion ` below for more information. | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``ol`` | None | ``li`` | Display an ordered list. See List elements below. | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ From 2ffcf952ae76f0ce923ef72a77e7a7e311f8a999 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 8 Apr 2020 12:28:01 +0100 Subject: [PATCH 374/459] Apply suggestions from code review Co-Authored-By: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/cpp/ql-for-cpp.rst | 4 ++-- docs/language/learn-ql/java/ql-for-java.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/cpp/ql-for-cpp.rst b/docs/language/learn-ql/cpp/ql-for-cpp.rst index b04c7cc3a88..bd52291a7f8 100644 --- a/docs/language/learn-ql/cpp/ql-for-cpp.rst +++ b/docs/language/learn-ql/cpp/ql-for-cpp.rst @@ -34,12 +34,12 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Detecting a potential buffer overflow `: You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. +- :doc:`Using the guards library in C and C++ `: You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases. + - :doc:`Using range analysis for C and C++ `: You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow. - :doc:`Hash consing and value numbering `: You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases. -- :doc:`Using the guards library in C and C++ `: You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases. - Further reading --------------- diff --git a/docs/language/learn-ql/java/ql-for-java.rst b/docs/language/learn-ql/java/ql-for-java.rst index a3c9cd79d71..3b5b64dd99b 100644 --- a/docs/language/learn-ql/java/ql-for-java.rst +++ b/docs/language/learn-ql/java/ql-for-java.rst @@ -18,7 +18,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - `Basic Java query `__: Learn to write and run a simple CodeQL query using LGTM. -- :doc:`CodeQL library for Java `: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for Java. +- :doc:`CodeQL library for Java `: When analyzing Java code, you can use the large collection of classes in the CodeQL library for Java. - :doc:`Analyzing data flow in Java `: You can use CodeQL to track the flow of data through a Java program to its use. From 7298b686742d6bf5300e7e6c31e39675feccf209 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 8 Apr 2020 13:34:57 +0200 Subject: [PATCH 375/459] C++: Exclude 'this' params and read/write side effects from static member function calls through qualifiers, and accept tests --- .../raw/internal/TranslatedCall.qll | 9 ++++ .../raw/internal/TranslatedElement.qll | 4 +- .../test/library-tests/ir/ir/raw_ir.expected | 44 +++++++------------ 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 088cb7fa4cd..3581e162172 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -324,6 +324,15 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { override predicate hasWriteSideEffect() { not expr.getTarget().(SideEffectFunction).hasOnlySpecificWriteSideEffects() } + + override Instruction getQualifierResult() { + hasQualifier() and + result = getQualifier().getResult() + } + + override predicate hasQualifier() { + not exists(MemberFunction func | expr.getTarget() = func and func.isStatic()) + } } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index c3788f4c8da..2f143bf02ca 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -463,7 +463,9 @@ newtype TTranslatedElement = expr = call.getArgument(n).getFullyConverted() or expr = call.getQualifier().getFullyConverted() and - n = -1 + n = -1 and + // Exclude calls to static member functions. They don't modify the qualifier + not exists(MemberFunction func | func = call.getTarget() and func.isStatic()) ) and ( call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(n, _) and diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index a50c9e1535d..d74ce2920b0 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6550,10 +6550,8 @@ ir.cpp: # 1272| r1272_1(glval) = VariableAddress[c] : # 1272| r1272_2(glval) = FunctionAddress[StaticMemberFunction] : # 1272| r1272_3(int) = Constant[10] : -# 1272| r1272_4(int) = Call : func:r1272_2, this:r1272_1, 0:r1272_3 +# 1272| r1272_4(int) = Call : func:r1272_2, 0:r1272_3 # 1272| mu1272_5(unknown) = ^CallSideEffect : ~mu1270_4 -# 1272| v1272_6(void) = ^BufferReadSideEffect[-1] : &:r1272_1, ~mu1270_4 -# 1272| mu1272_7(C) = ^IndirectMayWriteSideEffect[-1] : &:r1272_1 # 1273| r1273_1(glval) = FunctionAddress[StaticMemberFunction] : # 1273| r1273_2(int) = Constant[10] : # 1273| r1273_3(int) = Call : func:r1273_1, 0:r1273_2 @@ -6566,12 +6564,10 @@ ir.cpp: # 1276| r1276_4(A *) = CopyValue : r1276_3 # 1276| r1276_5(glval) = VariableAddress[int_arg] : # 1276| r1276_6(int) = Load : &:r1276_5, ~mu1270_4 -# 1276| v1276_7(void) = Call : func:r1276_2, this:r1276_1, 0:r1276_4, 1:r1276_6 +# 1276| v1276_7(void) = Call : func:r1276_2, 0:r1276_4, 1:r1276_6 # 1276| mu1276_8(unknown) = ^CallSideEffect : ~mu1270_4 -# 1276| v1276_9(void) = ^BufferReadSideEffect[-1] : &:r1276_1, ~mu1270_4 -# 1276| v1276_10(void) = ^BufferReadSideEffect[0] : &:r1276_4, ~mu1270_4 -# 1276| mu1276_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r1276_1 -# 1276| mu1276_12(unknown) = ^BufferMayWriteSideEffect[0] : &:r1276_4 +# 1276| v1276_9(void) = ^BufferReadSideEffect[0] : &:r1276_4, ~mu1270_4 +# 1276| mu1276_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1276_4 # 1277| r1277_1(glval) = FunctionAddress[static_member] : # 1277| r1277_2(glval) = VariableAddress[a] : # 1277| r1277_3(A *) = CopyValue : r1277_2 @@ -6590,12 +6586,10 @@ ir.cpp: # 1279| r1279_7(int) = Load : &:r1279_6, ~mu1270_4 # 1279| r1279_8(int) = Constant[2] : # 1279| r1279_9(int) = Add : r1279_7, r1279_8 -# 1279| v1279_10(void) = Call : func:r1279_3, this:r1279_2, 0:r1279_5, 1:r1279_9 +# 1279| v1279_10(void) = Call : func:r1279_3, 0:r1279_5, 1:r1279_9 # 1279| mu1279_11(unknown) = ^CallSideEffect : ~mu1270_4 -# 1279| v1279_12(void) = ^BufferReadSideEffect[-1] : &:r1279_2, ~mu1270_4 -# 1279| v1279_13(void) = ^BufferReadSideEffect[0] : &:r1279_5, ~mu1270_4 -# 1279| mu1279_14(A) = ^IndirectMayWriteSideEffect[-1] : &:r1279_2 -# 1279| mu1279_15(unknown) = ^BufferMayWriteSideEffect[0] : &:r1279_5 +# 1279| v1279_12(void) = ^BufferReadSideEffect[0] : &:r1279_5, ~mu1270_4 +# 1279| mu1279_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r1279_5 # 1280| r1280_1(glval) = VariableAddress[a_arg] : # 1280| r1280_2(A *) = Load : &:r1280_1, ~mu1270_4 # 1280| r1280_3(glval) = CopyValue : r1280_2 @@ -6603,30 +6597,24 @@ ir.cpp: # 1280| r1280_5(glval) = VariableAddress[a] : # 1280| r1280_6(A *) = CopyValue : r1280_5 # 1280| r1280_7(int) = Constant[99] : -# 1280| v1280_8(void) = Call : func:r1280_4, this:r1280_3, 0:r1280_6, 1:r1280_7 +# 1280| v1280_8(void) = Call : func:r1280_4, 0:r1280_6, 1:r1280_7 # 1280| mu1280_9(unknown) = ^CallSideEffect : ~mu1270_4 -# 1280| v1280_10(void) = ^BufferReadSideEffect[-1] : &:r1280_3, ~mu1270_4 -# 1280| v1280_11(void) = ^BufferReadSideEffect[0] : &:r1280_6, ~mu1270_4 -# 1280| mu1280_12(A) = ^IndirectMayWriteSideEffect[-1] : &:r1280_3 -# 1280| mu1280_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r1280_6 +# 1280| v1280_10(void) = ^BufferReadSideEffect[0] : &:r1280_6, ~mu1270_4 +# 1280| mu1280_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1280_6 # 1281| r1281_1(glval) = VariableAddress[a_arg] : # 1281| r1281_2(A *) = Load : &:r1281_1, ~mu1270_4 # 1281| r1281_3(glval) = FunctionAddress[static_member] : # 1281| r1281_4(glval) = VariableAddress[a_arg] : # 1281| r1281_5(A *) = Load : &:r1281_4, ~mu1270_4 # 1281| r1281_6(int) = Constant[-1] : -# 1281| v1281_7(void) = Call : func:r1281_3, this:r1281_2, 0:r1281_5, 1:r1281_6 +# 1281| v1281_7(void) = Call : func:r1281_3, 0:r1281_5, 1:r1281_6 # 1281| mu1281_8(unknown) = ^CallSideEffect : ~mu1270_4 -# 1281| v1281_9(void) = ^BufferReadSideEffect[-1] : &:r1281_2, ~mu1270_4 -# 1281| v1281_10(void) = ^BufferReadSideEffect[0] : &:r1281_5, ~mu1270_4 -# 1281| mu1281_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r1281_2 -# 1281| mu1281_12(unknown) = ^BufferMayWriteSideEffect[0] : &:r1281_5 +# 1281| v1281_9(void) = ^BufferReadSideEffect[0] : &:r1281_5, ~mu1270_4 +# 1281| mu1281_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1281_5 # 1283| r1283_1(glval) = VariableAddress[a] : # 1283| r1283_2(glval) = FunctionAddress[static_member_without_def] : -# 1283| v1283_3(void) = Call : func:r1283_2, this:r1283_1 +# 1283| v1283_3(void) = Call : func:r1283_2 # 1283| mu1283_4(unknown) = ^CallSideEffect : ~mu1270_4 -# 1283| v1283_5(void) = ^BufferReadSideEffect[-1] : &:r1283_1, ~mu1270_4 -# 1283| mu1283_6(A) = ^IndirectMayWriteSideEffect[-1] : &:r1283_1 # 1284| r1284_1(glval) = FunctionAddress[static_member_without_def] : # 1284| v1284_2(void) = Call : func:r1284_1 # 1284| mu1284_3(unknown) = ^CallSideEffect : ~mu1270_4 @@ -6634,10 +6622,8 @@ ir.cpp: # 1286| r1286_2(A *) = Call : func:r1286_1 # 1286| mu1286_3(unknown) = ^CallSideEffect : ~mu1270_4 # 1286| r1286_4(glval) = FunctionAddress[static_member_without_def] : -# 1286| v1286_5(void) = Call : func:r1286_4, this:r1286_2 +# 1286| v1286_5(void) = Call : func:r1286_4 # 1286| mu1286_6(unknown) = ^CallSideEffect : ~mu1270_4 -# 1286| v1286_7(void) = ^BufferReadSideEffect[-1] : &:r1286_2, ~mu1270_4 -# 1286| mu1286_8(A) = ^IndirectMayWriteSideEffect[-1] : &:r1286_2 # 1287| v1287_1(void) = NoOp : # 1270| v1270_11(void) = ReturnIndirection : &:r1270_9, ~mu1270_4 # 1270| v1270_12(void) = ReturnVoid : From 5ab595da2eba203f1908098432e0a1b655187b2d Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 8 Apr 2020 12:40:00 +0100 Subject: [PATCH 376/459] JS: Autoformat --- .../RecursionPrevention/SourceNodeFlowsTo.ql | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql index 2bc3990c1e7..9a5350948fe 100644 --- a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql +++ b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql @@ -4,16 +4,13 @@ * This tests adds a negative dependency `flowsTo --!--> SourceNode` * so that the undesired edge `SourceNode --> flowsTo` completes a negative cycle. */ + import javascript class BadSourceNode extends DataFlow::SourceNode { - BadSourceNode() { - this.(DataFlow::PropRead).getPropertyName() = "foo" - } + BadSourceNode() { this.(DataFlow::PropRead).getPropertyName() = "foo" } - override predicate flowsTo(DataFlow::Node node) { - not node instanceof DataFlow::SourceNode - } + override predicate flowsTo(DataFlow::Node node) { not node instanceof DataFlow::SourceNode } } select "Success" From 32c04ad76556f2b9e11c490da475a01dd26acba7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 8 Apr 2020 16:46:33 +0200 Subject: [PATCH 377/459] Python: Use getAbsolutePath() instead of deprecated getName() --- python/ql/src/external/CodeDuplication.qll | 2 +- python/ql/src/external/DefectFilter.qll | 4 ++-- python/ql/src/external/VCS.qll | 2 +- python/ql/src/semmle/python/filters/GeneratedCode.qll | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/src/external/CodeDuplication.qll b/python/ql/src/external/CodeDuplication.qll index c195d16ae6a..d558ee7e8a7 100644 --- a/python/ql/src/external/CodeDuplication.qll +++ b/python/ql/src/external/CodeDuplication.qll @@ -66,7 +66,7 @@ class Copy extends @duplication_or_similarity { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - sourceFile().getName() = filepath and + sourceFile().getAbsolutePath() = filepath and startline = sourceStartLine() and startcolumn = sourceStartColumn() and endline = sourceEndLine() and diff --git a/python/ql/src/external/DefectFilter.qll b/python/ql/src/external/DefectFilter.qll index 6d5f75510cf..38419dee2ec 100644 --- a/python/ql/src/external/DefectFilter.qll +++ b/python/ql/src/external/DefectFilter.qll @@ -26,7 +26,7 @@ class DefectResult extends int { /** Gets the file in which this query result was reported. */ File getFile() { - exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getName() = path) + exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path) } /** Gets the file path in which this query result was reported. */ @@ -54,7 +54,7 @@ class DefectResult extends int { /** Gets the URL corresponding to the location of this query result. */ string getURL() { result = - "file://" + getFile().getName() + ":" + getStartLine() + ":" + getStartColumn() + ":" + + "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" + getEndLine() + ":" + getEndColumn() } } diff --git a/python/ql/src/external/VCS.qll b/python/ql/src/external/VCS.qll index 2d03f7d882d..0212dbfbd24 100644 --- a/python/ql/src/external/VCS.qll +++ b/python/ql/src/external/VCS.qll @@ -23,7 +23,7 @@ class Commit extends @svnentry { string getMessage() { svnentrymsg(this, result) } string getAnAffectedFilePath(string action) { - exists(File rawFile | svnaffectedfiles(this, rawFile, action) | result = rawFile.getName()) + exists(File rawFile | svnaffectedfiles(this, rawFile, action) | result = rawFile.getAbsolutePath()) } string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) } diff --git a/python/ql/src/semmle/python/filters/GeneratedCode.qll b/python/ql/src/semmle/python/filters/GeneratedCode.qll index 411cb558e7e..5b1721945da 100644 --- a/python/ql/src/semmle/python/filters/GeneratedCode.qll +++ b/python/ql/src/semmle/python/filters/GeneratedCode.qll @@ -170,7 +170,7 @@ string from_mako_import(Module m) { /** File generated by Google's protobuf tool. */ class ProtobufGeneratedFile extends SpecificGeneratedFile { ProtobufGeneratedFile() { - this.getName().regexpMatch(".*_pb2?.py") and + this.getAbsolutePath().regexpMatch(".*_pb2?.py") and exists(Module m | m.getFile() = this | exists(ImportExpr imp | imp.getEnclosingModule() = m | imp.getImportedModuleName() = "google.net.proto2.python.public" From a2440f0fcd879965c95fab28f89fe429d8a3b268 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 8 Apr 2020 16:53:19 +0200 Subject: [PATCH 378/459] Python: Modernise semmle/python/dataflow/Files.qll --- python/ql/src/semmle/python/dataflow/Files.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/Files.qll b/python/ql/src/semmle/python/dataflow/Files.qll index 651b7a93850..467a8bec29e 100644 --- a/python/ql/src/semmle/python/dataflow/Files.qll +++ b/python/ql/src/semmle/python/dataflow/Files.qll @@ -11,7 +11,7 @@ class OpenFileConfiguration extends TaintTracking::Configuration { OpenFileConfiguration() { this = "Open file configuration" } override predicate isSource(DataFlow::Node src, TaintKind kind) { - theOpenFunction().(FunctionObject).getACall() = src.asCfgNode() and + src.asCfgNode() = Value::named("open").getACall() and kind instanceof OpenFile } From 47934310efe81f30a2aa17efa70b90752425ec8a Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 8 Apr 2020 19:58:36 +0100 Subject: [PATCH 379/459] JS: Hide captured nodes in path explanations --- .../ql/src/semmle/javascript/dataflow/Configuration.qll | 3 +++ .../ql/src/semmle/javascript/dataflow/DataFlow.qll | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 1406c19a518..e57c0764000 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -1462,6 +1462,9 @@ class MidPathNode extends PathNode, MkMidNode { or // Skip the synthetic 'this' node, as a ThisExpr will be the next node anyway nd = DataFlow::thisNode(_) + or + // Skip captured variable nodes as the successor will be a use of that variable anyway. + nd = DataFlow::capturedVariableNode(_) } } diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index d4d7e3bff16..18365e16770 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -1245,6 +1245,15 @@ module DataFlow { } } + /** + * INTERNAL. DO NOT USE. + * + * Gets a data flow node representing the given captured variable. + */ + Node capturedVariableNode(LocalVariable variable) { + result = TCapturedVariableNode(variable) + } + /** * Gets the data flow node corresponding to `nd`. * From a0b26d66a4118e1eb9c45ff9297b9144eeb8018e Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 8 Apr 2020 13:55:41 -0700 Subject: [PATCH 380/459] C++: remove partial flow to IR loads --- cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 12857dd05e9..9385d6730e4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -199,8 +199,6 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Flow through pointer dereference i2.(LoadInstruction).getSourceAddress() = i1 or - i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 - or i2.(UnaryInstruction).getUnary() = i1 or // Flow out of definition-by-reference From 9f40886af9caad9ea6a96486efbeab42ebc861d5 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 8 Apr 2020 15:25:26 +0200 Subject: [PATCH 381/459] C++: Don't allow taint out of a field read except if it's from a union. This prevents field conflation through buffers of `UnknownType`. --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 9385d6730e4..61d941a6f44 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -199,7 +199,19 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Flow through pointer dereference i2.(LoadInstruction).getSourceAddress() = i1 or - i2.(UnaryInstruction).getUnary() = i1 + // Unary instructions tend to preserve enough information in practice that we + // want taint to flow through. + // The exception is `FieldAddressInstruction`. Together with the rule for + // `LoadInstruction` above and for `ChiInstruction` below, flow through + // `FieldAddressInstruction` could cause flow into one field to come out an + // unrelated field. This would happen across function boundaries, where the IR + // would not be able to match loads to stores. + i2.(UnaryInstruction).getUnary() = i1 and + ( + not i2 instanceof FieldAddressInstruction + or + i2.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union + ) or // Flow out of definition-by-reference i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and @@ -213,7 +225,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { or t instanceof ArrayType or - // Buffers or unknown size + // Buffers of unknown size t instanceof UnknownType ) or From b37c13de914edf30743c992b63f600d49e59a455 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 8 Apr 2020 16:29:50 -0700 Subject: [PATCH 382/459] C++: restore flow for non-class partial reads This would otherwise have lost a good qltest result at CWE-134/semmle/funcs/funcsLocal.c:58:9:58:10 --- .../code/cpp/ir/dataflow/DefaultTaintTracking.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 61d941a6f44..523a64576b1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -199,6 +199,17 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Flow through pointer dereference i2.(LoadInstruction).getSourceAddress() = i1 or + // Flow through partial reads of arrays, unions, and pointer parameters + // TODO: `UnknownType` includes *all* pointer parameters. We only want + // array-like pointer parameters + i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 and + not i1.isResultConflated() and + ( + i1.getResultType() instanceof ArrayType or + i1.getResultType() instanceof UnknownType or + i1.getResultType() instanceof Union + ) + or // Unary instructions tend to preserve enough information in practice that we // want taint to flow through. // The exception is `FieldAddressInstruction`. Together with the rule for From 7e299e74948959d80b55fe808271ca04bea702ac Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 8 Apr 2020 16:39:50 -0700 Subject: [PATCH 383/459] C++/C#: Document ReturnIndirectionInstruction::getParameter --- .../code/cpp/ir/implementation/aliased_ssa/Instruction.qll | 4 ++++ .../src/semmle/code/cpp/ir/implementation/raw/Instruction.qll | 4 ++++ .../code/cpp/ir/implementation/unaliased_ssa/Instruction.qll | 4 ++++ .../semmle/code/csharp/ir/implementation/raw/Instruction.qll | 4 ++++ .../csharp/ir/implementation/unaliased_ssa/Instruction.qll | 4 ++++ 5 files changed, 20 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index b6d834f1fdd..38216872f2b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -536,6 +536,10 @@ class ReturnIndirectionInstruction extends VariableInstruction { final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index b6d834f1fdd..38216872f2b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -536,6 +536,10 @@ class ReturnIndirectionInstruction extends VariableInstruction { final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index b6d834f1fdd..38216872f2b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -536,6 +536,10 @@ class ReturnIndirectionInstruction extends VariableInstruction { final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index b6d834f1fdd..38216872f2b 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -536,6 +536,10 @@ class ReturnIndirectionInstruction extends VariableInstruction { final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index b6d834f1fdd..38216872f2b 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -536,6 +536,10 @@ class ReturnIndirectionInstruction extends VariableInstruction { final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } From 1199ff92e857ee04e18a49a71e1b517a49743e90 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 8 Apr 2020 16:41:29 -0700 Subject: [PATCH 384/459] C++: autoformat --- .../code/cpp/ir/dataflow/internal/DataFlowDispatch.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index 55378ed36ef..1dd1d9ac4cc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -126,10 +126,12 @@ private module VirtualDispatch { /** * A ReturnNode with its ReturnKind and its enclosing callable. - * + * * Used to fix a join ordering issue in flowsFrom. */ - private predicate returnNodeWithKindAndEnclosingCallable(ReturnNode node, ReturnKind kind, DataFlowCallable callable) { + private predicate returnNodeWithKindAndEnclosingCallable( + ReturnNode node, ReturnKind kind, DataFlowCallable callable + ) { node.getKind() = kind and node.getEnclosingCallable() = callable } From 3b591183c9329a18da24d13fa34f79cdc50e2684 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 8 Apr 2020 17:09:30 -0700 Subject: [PATCH 385/459] C++: remove partial flow from UnknownType --- .../semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 523a64576b1..dbeefae4880 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -199,17 +199,14 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Flow through pointer dereference i2.(LoadInstruction).getSourceAddress() = i1 or - // Flow through partial reads of arrays, unions, and pointer parameters - // TODO: `UnknownType` includes *all* pointer parameters. We only want - // array-like pointer parameters + // Flow through partial reads of arrays and unions i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 and not i1.isResultConflated() and ( i1.getResultType() instanceof ArrayType or - i1.getResultType() instanceof UnknownType or i1.getResultType() instanceof Union - ) - or + ) + or // Unary instructions tend to preserve enough information in practice that we // want taint to flow through. // The exception is `FieldAddressInstruction`. Together with the rule for From 6c7e1cdd46eabaec92330874fe95bfb9554d4b90 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 9 Apr 2020 08:22:47 +0200 Subject: [PATCH 386/459] C++: Make sure non-member functions are not reported to have a qualifier --- .../code/cpp/ir/implementation/raw/internal/TranslatedCall.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 3581e162172..22f104e12c8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -331,6 +331,7 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { } override predicate hasQualifier() { + exists(getQualifier()) and not exists(MemberFunction func | expr.getTarget() = func and func.isStatic()) } } From d9f81b082b395f5177262c2c1ea3029bc7df7460 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 9 Apr 2020 07:45:00 +0100 Subject: [PATCH 387/459] JS: Autoformat --- javascript/ql/src/semmle/javascript/Variables.qll | 7 ++++++- .../ql/src/semmle/javascript/dataflow/DataFlow.qll | 12 +++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Variables.qll b/javascript/ql/src/semmle/javascript/Variables.qll index bef027d6fbd..238ecef4687 100644 --- a/javascript/ql/src/semmle/javascript/Variables.qll +++ b/javascript/ql/src/semmle/javascript/Variables.qll @@ -325,7 +325,12 @@ class LocalVariable extends Variable { * If it has no declaration, the location of its declaring scope is used. */ Location getLocation() { - result = min(Location loc | loc = getADeclaration().getLocation() | loc order by loc.getStartLine(), loc.getStartColumn() ) + result = + min(Location loc | + loc = getADeclaration().getLocation() + | + loc order by loc.getStartLine(), loc.getStartColumn() + ) or not exists(getADeclaration()) and result = getDeclaringContainer().getLocation() diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 18365e16770..8b014a2d00c 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -1230,9 +1230,7 @@ module DataFlow { CapturedVariableNode() { this = TCapturedVariableNode(variable) } - override BasicBlock getBasicBlock() { - result = variable.getDeclaringContainer().getStartBB() - } + override BasicBlock getBasicBlock() { result = variable.getDeclaringContainer().getStartBB() } override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn @@ -1240,9 +1238,7 @@ module DataFlow { variable.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } - override string toString() { - result = variable.getName() - } + override string toString() { result = variable.getName() } } /** @@ -1250,9 +1246,7 @@ module DataFlow { * * Gets a data flow node representing the given captured variable. */ - Node capturedVariableNode(LocalVariable variable) { - result = TCapturedVariableNode(variable) - } + Node capturedVariableNode(LocalVariable variable) { result = TCapturedVariableNode(variable) } /** * Gets the data flow node corresponding to `nd`. From 25d5cc78cb8a065f2409bf311c1efcdcaeced3e2 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 9 Apr 2020 09:18:26 +0100 Subject: [PATCH 388/459] JS: Use entry location instead of whole container --- javascript/ql/src/semmle/javascript/Variables.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Variables.qll b/javascript/ql/src/semmle/javascript/Variables.qll index 238ecef4687..ede33788841 100644 --- a/javascript/ql/src/semmle/javascript/Variables.qll +++ b/javascript/ql/src/semmle/javascript/Variables.qll @@ -322,7 +322,7 @@ class LocalVariable extends Variable { * Gets the location of a declaration of this variable. * * If the variable has multiple declarations, an arbitrary one is used. - * If it has no declaration, the location of its declaring scope is used. + * If it has no declaration, the entry point of its declaring container is used. */ Location getLocation() { result = @@ -333,7 +333,7 @@ class LocalVariable extends Variable { ) or not exists(getADeclaration()) and - result = getDeclaringContainer().getLocation() + result = getDeclaringContainer().getEntry().getLocation() } } From 0c5bca8f4e7ed251bd06c2704f604b26b8cc9595 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 9 Apr 2020 12:09:15 +0200 Subject: [PATCH 389/459] C++: Replace underscores with dashes in query @id --- cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql index fb7edce038c..04b3d13a3f7 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql @@ -3,7 +3,7 @@ * @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols. * @kind problem * @problem.severity error - * @id cpp/boost/tls_settings_misconfiguration + * @id cpp/boost/tls-settings-misconfiguration * @tags security */ From f7b3205cae2841f60b0f9007ba7f321a87cdd6c1 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 9 Apr 2020 12:19:58 +0100 Subject: [PATCH 390/459] docs: move supported frameworks into single reusable --- docs/language/support/csharp-frameworks.csv | 9 -- docs/language/support/framework-support.rst | 38 +------- docs/language/support/java-frameworks.csv | 13 --- .../javascript-typescript-frameworks.csv | 23 ----- docs/language/support/python-frameworks.csv | 11 --- .../language/support/reusables/frameworks.rst | 95 +++++++++++++++++++ docs/language/support/versions-compilers.rst | 33 ------- 7 files changed, 96 insertions(+), 126 deletions(-) delete mode 100644 docs/language/support/csharp-frameworks.csv delete mode 100644 docs/language/support/java-frameworks.csv delete mode 100644 docs/language/support/javascript-typescript-frameworks.csv delete mode 100644 docs/language/support/python-frameworks.csv create mode 100644 docs/language/support/reusables/frameworks.rst delete mode 100644 docs/language/support/versions-compilers.rst diff --git a/docs/language/support/csharp-frameworks.csv b/docs/language/support/csharp-frameworks.csv deleted file mode 100644 index 28b0b3bb06c..00000000000 --- a/docs/language/support/csharp-frameworks.csv +++ /dev/null @@ -1,9 +0,0 @@ -Name, Category -ASP.NET, Web application framework -ASP.NET Core, Web application framework -ASP.NET Razor templates, Web application framework -EntityFramework, Database ORM -EntityFramework Core, Database ORM -Json.NET, Serialization -NHibernate, Database ORM -WinForms, User interface diff --git a/docs/language/support/framework-support.rst b/docs/language/support/framework-support.rst index 71455b983ec..37d54829475 100644 --- a/docs/language/support/framework-support.rst +++ b/docs/language/support/framework-support.rst @@ -12,40 +12,4 @@ The libraries and queries in version |version| have been explicitly checked agai .. There is currently no built-in support for libraries or frameworks for C/C++. -C# built-in support -================================ - -.. csv-table:: - :file: csharp-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto - -Java built-in support -================================== - -.. csv-table:: - :file: java-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto - - -JavaScript and TypeScript built-in support -======================================================= - -.. csv-table:: - :file: javascript-typescript-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto - - -Python built-in support -==================================== - -.. csv-table:: - :file: python-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto +.. include:: reusables/frameworks.rst diff --git a/docs/language/support/java-frameworks.csv b/docs/language/support/java-frameworks.csv deleted file mode 100644 index 876d0ae111c..00000000000 --- a/docs/language/support/java-frameworks.csv +++ /dev/null @@ -1,13 +0,0 @@ -Name, Category -Hibernate, Database -iBatis / MyBatis, Database -Java Persistence API (JPA), Database -JDBC, Database -Protobuf, Serialization -Kryo deserialization, Serialization -SnakeYaml, Serialization -Spring JDBC, Database -Spring MVC, Web application framework -Struts, Web application framework -Thrift, RPC framework -XStream, Serialization diff --git a/docs/language/support/javascript-typescript-frameworks.csv b/docs/language/support/javascript-typescript-frameworks.csv deleted file mode 100644 index abed9dc5113..00000000000 --- a/docs/language/support/javascript-typescript-frameworks.csv +++ /dev/null @@ -1,23 +0,0 @@ -Name, Category -angularjs, HTML framework -axios, Network communicator -browser, Runtime environment -electron, Runtime environment -express, Server -hapi, Server -jquery, Utility library -koa, Server -lodash, Utility library -mongodb, Database -mssql, Database -mysql, Database -node, Runtime environment -postgres, Database -ramda, Utility library -react, HTML framework -request, Network communicator -sequelize, Database -socket.io, Network communicator -sqlite3, Database -superagent, Network communicator -underscore, Utility library diff --git a/docs/language/support/python-frameworks.csv b/docs/language/support/python-frameworks.csv deleted file mode 100644 index 7a5e78d8756..00000000000 --- a/docs/language/support/python-frameworks.csv +++ /dev/null @@ -1,11 +0,0 @@ -Name, Category -Bottle, Web framework -CherryPy, Web framework -Django, Web application framework -Falcon, Web API framework -Flask, Microframework -Pyramid, Web application framework -Tornado, Web application framework and asynchronous networking library -Turbogears, Web framework -Twisted, Networking engine -WebOb, WSGI request library diff --git a/docs/language/support/reusables/frameworks.rst b/docs/language/support/reusables/frameworks.rst new file mode 100644 index 00000000000..1b8e85e60e2 --- /dev/null +++ b/docs/language/support/reusables/frameworks.rst @@ -0,0 +1,95 @@ +.. There is currently no built-in support for libraries or frameworks for C/C++. + +C# built-in support +================================ + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + ASP.NET, Web application framework + ASP.NET Core, Web application framework + ASP.NET Razor templates, Web application framework + EntityFramework, Database ORM + EntityFramework Core, Database ORM + Json.NET, Serialization + NHibernate, Database ORM + WinForms, User interface + +Java built-in support +================================== + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + Hibernate, Database + iBatis / MyBatis, Database + Java Persistence API (JPA), Database + JDBC, Database + Protobuf, Serialization + Kryo deserialization, Serialization + SnakeYaml, Serialization + Spring JDBC, Database + Spring MVC, Web application framework + Struts, Web application framework + Thrift, RPC framework + XStream, Serialization + +JavaScript and TypeScript built-in support +======================================================= + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + angularjs, HTML framework + axios, Network communicator + browser, Runtime environment + electron, Runtime environment + express, Server + hapi, Server + jquery, Utility library + koa, Server + lodash, Utility library + mongodb, Database + mssql, Database + mysql, Database + node, Runtime environment + postgres, Database + ramda, Utility library + react, HTML framework + request, Network communicator + sequelize, Database + socket.io, Network communicator + sqlite3, Database + superagent, Network communicator + underscore, Utility library + + + +Python built-in support +==================================== + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + Bottle, Web framework + CherryPy, Web framework + Django, Web application framework + Falcon, Web API framework + Flask, Microframework + Pyramid, Web application framework + Tornado, Web application framework and asynchronous networking library + Turbogears, Web framework + Twisted, Networking engine + WebOb, WSGI request library diff --git a/docs/language/support/versions-compilers.rst b/docs/language/support/versions-compilers.rst deleted file mode 100644 index 3b244e592bd..00000000000 --- a/docs/language/support/versions-compilers.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. csv-table:: - :header-rows: 1 - :widths: auto - :stub-columns: 1 - - Language,Variants,Compilers,Extensions - C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0), - - GNU extensions (up to GCC 9.2), - - Microsoft extensions (up to VS 2019), - - Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" - C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019, - - .NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" - Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go`` - Java,"Java 6 to 14 [4]_","javac (OpenJDK and Oracle JDK), - - Eclipse compiler for Java (ECJ) [5]_",``.java`` - JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" - Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py`` - TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``" - -.. container:: footnote-group - - .. [1] Support for the clang-cl compiler is preliminary. - .. [2] Support for the Arm Compiler (armcc) is preliminary. - .. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0. - .. [4] Builds that execute on Java 6 to 14 can be analyzed. The analysis understands Java 14 standard language features. - .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. - .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. - .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. From 878109ccc49c8e8963ca3aa31050e1ea5f374164 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 9 Apr 2020 12:20:27 +0100 Subject: [PATCH 391/459] docs: move language support into reusables folders --- docs/language/support/conf.py | 2 +- docs/language/support/language-support.rst | 2 +- .../support/reusables/versions-compilers.rst | 33 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 docs/language/support/reusables/versions-compilers.rst diff --git a/docs/language/support/conf.py b/docs/language/support/conf.py index 30d7b1a3028..e88bdfce1bb 100644 --- a/docs/language/support/conf.py +++ b/docs/language/support/conf.py @@ -80,4 +80,4 @@ htmlhelp_basename = 'Supported languages and frameworks' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['read-me-project.rst'] \ No newline at end of file +exclude_patterns = ['read-me-project.rst', 'reusables/*'] \ No newline at end of file diff --git a/docs/language/support/language-support.rst b/docs/language/support/language-support.rst index 4ffd28f3797..4aebb9957d6 100644 --- a/docs/language/support/language-support.rst +++ b/docs/language/support/language-support.rst @@ -10,4 +10,4 @@ Customers with any questions should contact their usual Semmle contact with any If you're not a customer yet, contact us at info@semmle.com with any questions you have about language and compiler support. -.. include:: versions-compilers.rst +.. include:: reusables/versions-compilers.rst diff --git a/docs/language/support/reusables/versions-compilers.rst b/docs/language/support/reusables/versions-compilers.rst new file mode 100644 index 00000000000..3b244e592bd --- /dev/null +++ b/docs/language/support/reusables/versions-compilers.rst @@ -0,0 +1,33 @@ +.. csv-table:: + :header-rows: 1 + :widths: auto + :stub-columns: 1 + + Language,Variants,Compilers,Extensions + C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0), + + GNU extensions (up to GCC 9.2), + + Microsoft extensions (up to VS 2019), + + Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" + C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019, + + .NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" + Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go`` + Java,"Java 6 to 14 [4]_","javac (OpenJDK and Oracle JDK), + + Eclipse compiler for Java (ECJ) [5]_",``.java`` + JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" + Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py`` + TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``" + +.. container:: footnote-group + + .. [1] Support for the clang-cl compiler is preliminary. + .. [2] Support for the Arm Compiler (armcc) is preliminary. + .. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0. + .. [4] Builds that execute on Java 6 to 14 can be analyzed. The analysis understands Java 14 standard language features. + .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. + .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. + .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. From c070416fbe0e6e4b0966ada924156e7a0b10c030 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 9 Apr 2020 12:24:11 +0100 Subject: [PATCH 392/459] JS: Update test output --- .../library-tests/DataFlow/flowStep.expected | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/javascript/ql/test/library-tests/DataFlow/flowStep.expected b/javascript/ql/test/library-tests/DataFlow/flowStep.expected index 4bb0eabd7f6..fbc30cb0ec0 100644 --- a/javascript/ql/test/library-tests/DataFlow/flowStep.expected +++ b/javascript/ql/test/library-tests/DataFlow/flowStep.expected @@ -13,10 +13,11 @@ | sources.js:11:12:11:18 | key | sources.js:11:32:11:34 | key | | sources.js:11:14:11:16 | key | sources.js:11:12:11:18 | key | | tst2.ts:1:1:1:1 | A | tst2.ts:1:18:1:18 | A | -| tst2.ts:1:1:1:1 | A | tst2.ts:7:1:7:0 | A | -| tst2.ts:1:8:5:1 | A | tst2.ts:7:1:7:0 | A | +| tst2.ts:1:1:1:1 | A | tst2.ts:1:18:1:18 | A | +| tst2.ts:1:8:5:1 | A | tst2.ts:1:18:1:18 | A | | tst2.ts:1:8:5:1 | A | tst2.ts:11:11:11:11 | A | | tst2.ts:1:8:5:1 | namespa ... lysed\\n} | tst2.ts:1:8:5:1 | A | +| tst2.ts:1:18:1:18 | A | tst2.ts:7:1:7:0 | A | | tst2.ts:2:14:2:19 | x | tst2.ts:4:3:4:3 | x | | tst2.ts:2:18:2:19 | 42 | tst2.ts:2:14:2:19 | x | | tst2.ts:7:1:7:0 | A | tst2.ts:8:3:8:3 | A | @@ -26,19 +27,19 @@ | tst2.ts:11:11:11:13 | A.x | tst2.ts:11:11:11:23 | A.x as number | | tst2.ts:13:26:13:29 | List | tst2.ts:13:26:13:37 | List | | tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | -| tst.js:1:1:1:1 | x | tst.js:28:2:28:1 | x | -| tst.js:1:1:1:1 | x | tst.js:32:1:32:0 | x | +| tst.js:1:1:1:1 | x | tst.js:3:5:3:5 | x | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:7:1:7:2 | fs | | tst.js:1:10:1:11 | fs | tst.js:22:24:22:25 | fs | +| tst.js:3:5:3:5 | x | tst.js:28:2:28:1 | x | +| tst.js:3:5:3:5 | x | tst.js:32:1:32:0 | x | +| tst.js:3:5:3:10 | x | tst.js:3:5:3:5 | x | | tst.js:3:5:3:10 | x | tst.js:8:1:8:1 | x | | tst.js:3:5:3:10 | x | tst.js:9:2:9:2 | x | | tst.js:3:5:3:10 | x | tst.js:10:1:10:1 | x | | tst.js:3:5:3:10 | x | tst.js:11:1:11:1 | x | | tst.js:3:5:3:10 | x | tst.js:11:1:11:1 | x | | tst.js:3:5:3:10 | x | tst.js:11:1:11:1 | x | -| tst.js:3:5:3:10 | x | tst.js:28:2:28:1 | x | -| tst.js:3:5:3:10 | x | tst.js:32:1:32:0 | x | | tst.js:3:9:3:10 | 42 | tst.js:3:5:3:10 | x | | tst.js:4:5:4:12 | y | tst.js:10:4:10:4 | y | | tst.js:4:5:4:12 | y | tst.js:11:6:11:6 | y | @@ -75,9 +76,8 @@ | tst.js:22:5:22:25 | readFileSync | tst.js:23:1:23:12 | readFileSync | | tst.js:22:7:22:18 | readFileSync | tst.js:22:5:22:25 | readFileSync | | tst.js:22:24:22:25 | fs | tst.js:22:5:22:20 | { readFileSync } | +| tst.js:25:1:25:3 | x | tst.js:3:5:3:5 | x | | tst.js:25:1:25:3 | x | tst.js:26:1:26:1 | x | -| tst.js:25:1:25:3 | x | tst.js:28:2:28:1 | x | -| tst.js:25:1:25:3 | x | tst.js:32:1:32:0 | x | | tst.js:25:1:25:3 | x | tst.js:57:7:57:7 | x | | tst.js:25:1:25:3 | x | tst.js:58:11:58:11 | x | | tst.js:25:1:25:3 | x | tst.js:105:1:105:1 | x | From 5af7d5f03a060007f1d48efc07405fcbf16cc67c Mon Sep 17 00:00:00 2001 From: Henry Mercer Date: Thu, 9 Apr 2020 13:06:53 +0100 Subject: [PATCH 393/459] Update README to reflect new license Per https://github.com/Semmle/ql/pull/3205, code is now licensed under the MIT License. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f77856cfc4..7d2fb59bf1a 100644 --- a/README.md +++ b/README.md @@ -13,4 +13,4 @@ We welcome contributions to our standard library and standard checks. Do you hav ## License -The code in this repository is licensed under [Apache License 2.0](LICENSE) by [GitHub](https://github.com). +The code in this repository is licensed under the [MIT License](LICENSE) by [GitHub](https://github.com). From febbbc4423285f892e675f5f8af097df1485a1a9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 9 Apr 2020 11:25:37 +0100 Subject: [PATCH 394/459] C++: Additional test cases. --- .../TaintedAllocationSize.expected | 103 ++++++++++++++++++ .../semmle/TaintedAllocationSize/test.cpp | 48 +++++++- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 3847e91bbc8..4aa02918186 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -69,6 +69,62 @@ edges | test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:14 | size | | test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | | test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | +| test.cpp:201:9:201:12 | call to atoi | test.cpp:201:9:201:12 | call to atoi | +| test.cpp:201:9:201:12 | call to atoi | test.cpp:201:9:201:28 | (unsigned long)... | +| test.cpp:201:9:201:12 | call to atoi | test.cpp:201:9:201:42 | Store | +| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | +| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | +| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | +| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | +| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | +| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:28 | (unsigned long)... | +| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:42 | Store | +| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:12 | call to atoi | +| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:12 | call to atoi | +| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:12 | call to atoi | +| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:28 | (unsigned long)... | +| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:42 | Store | +| test.cpp:206:13:206:16 | call to atoi | test.cpp:206:13:206:16 | call to atoi | +| test.cpp:206:13:206:16 | call to atoi | test.cpp:206:13:206:32 | (unsigned long)... | +| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | +| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | +| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | +| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:32 | (unsigned long)... | +| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:16 | call to atoi | +| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:16 | call to atoi | +| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:16 | call to atoi | +| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:32 | (unsigned long)... | +| test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | +| test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | +| test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | +| test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | +| test.cpp:227:19:227:22 | call to atoi | test.cpp:227:19:227:22 | call to atoi | +| test.cpp:227:19:227:22 | call to atoi | test.cpp:227:19:227:38 | (unsigned long)... | +| test.cpp:227:19:227:22 | call to atoi | test.cpp:229:9:229:18 | (size_t)... | +| test.cpp:227:19:227:22 | call to atoi | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:19:227:22 | call to atoi | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:19:227:22 | call to atoi | test.cpp:235:11:235:20 | (size_t)... | +| test.cpp:227:19:227:22 | call to atoi | test.cpp:237:10:237:19 | (size_t)... | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:38 | (unsigned long)... | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | (size_t)... | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:235:11:235:20 | (size_t)... | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:237:10:237:19 | (size_t)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:22 | call to atoi | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:22 | call to atoi | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:22 | call to atoi | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:38 | (unsigned long)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | (size_t)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:235:11:235:20 | (size_t)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:237:10:237:19 | (size_t)... | +| test.cpp:235:11:235:20 | (size_t)... | test.cpp:214:23:214:23 | s | +| test.cpp:237:10:237:19 | (size_t)... | test.cpp:220:21:220:21 | s | nodes | test.cpp:39:21:39:24 | argv | semmle.label | argv | | test.cpp:39:21:39:24 | argv | semmle.label | argv | @@ -134,6 +190,46 @@ nodes | test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | | test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | | test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | +| test.cpp:201:9:201:12 | call to atoi | semmle.label | call to atoi | +| test.cpp:201:9:201:12 | call to atoi | semmle.label | call to atoi | +| test.cpp:201:9:201:12 | call to atoi | semmle.label | call to atoi | +| test.cpp:201:9:201:28 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:201:9:201:28 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:201:9:201:42 | Store | semmle.label | Store | +| test.cpp:201:14:201:19 | call to getenv | semmle.label | call to getenv | +| test.cpp:201:14:201:27 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:206:13:206:16 | call to atoi | semmle.label | call to atoi | +| test.cpp:206:13:206:16 | call to atoi | semmle.label | call to atoi | +| test.cpp:206:13:206:16 | call to atoi | semmle.label | call to atoi | +| test.cpp:206:13:206:32 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:206:13:206:32 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:206:18:206:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:206:18:206:31 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:214:23:214:23 | s | semmle.label | s | +| test.cpp:215:21:215:21 | s | semmle.label | s | +| test.cpp:215:21:215:21 | s | semmle.label | s | +| test.cpp:215:21:215:21 | s | semmle.label | s | +| test.cpp:220:21:220:21 | s | semmle.label | s | +| test.cpp:221:21:221:21 | s | semmle.label | s | +| test.cpp:221:21:221:21 | s | semmle.label | s | +| test.cpp:221:21:221:21 | s | semmle.label | s | +| test.cpp:227:19:227:22 | call to atoi | semmle.label | call to atoi | +| test.cpp:227:19:227:22 | call to atoi | semmle.label | call to atoi | +| test.cpp:227:19:227:22 | call to atoi | semmle.label | call to atoi | +| test.cpp:227:19:227:38 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:227:19:227:38 | (unsigned long)... | semmle.label | (unsigned long)... | +| test.cpp:227:24:227:29 | call to getenv | semmle.label | call to getenv | +| test.cpp:227:24:227:37 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | +| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | +| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | +| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | +| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | +| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | +| test.cpp:235:11:235:20 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... | #select | test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | @@ -149,3 +245,10 @@ nodes | test.cpp:134:10:134:27 | ... * ... | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:13 | size | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | | test.cpp:142:4:142:9 | call to malloc | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | | test.cpp:142:11:142:28 | ... * ... | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:14 | size | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | +| test.cpp:201:9:201:42 | ... * ... | test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) | +| test.cpp:206:13:206:46 | ... * ... | test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | This allocation size is derived from $@ and might overflow | test.cpp:206:18:206:23 | call to getenv | user input (getenv) | +| test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | +| test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | +| test.cpp:227:19:227:52 | ... * ... | test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | +| test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | +| test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp index 4a1bbd8a9dc..cb21e8f1915 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp @@ -5,8 +5,8 @@ typedef struct {} FILE; void *malloc(size_t size); void *realloc(void *ptr, size_t size); +void free(void *ptr); int atoi(const char *nptr); - struct MyStruct { char data[256]; @@ -190,3 +190,49 @@ void more_bounded_tests() { } } } + +size_t get_untainted_size() +{ + return 10 * sizeof(int); +} + +size_t get_tainted_size() +{ + return atoi(getenv("USER")) * sizeof(int); +} + +size_t get_bounded_size() +{ + size_t s = atoi(getenv("USER")) * sizeof(int); + + if (s < 0) { s = 0; } + if (s > 100) { s = 100; } + + return s; +} + +void *my_alloc(size_t s) { + void *ptr = malloc(s); // [UNHELPFUL RESULT] + + return ptr; +} + +void my_func(size_t s) { + void *ptr = malloc(s); // BAD + + free(ptr); +} + +void more_cases() { + int local_size = atoi(getenv("USER")) * sizeof(int); + + malloc(local_size); // BAD + malloc(get_untainted_size()); // GOOD + malloc(get_tainted_size()); // BAD + malloc(get_bounded_size()); // GOOD + + my_alloc(100); // GOOD + my_alloc(local_size); // BAD [NOT DETECTED IN CORRECT LOCATION] + my_func(100); // GOOD + my_func(local_size); // GOOD +} From a7979fdc12405d22aa1d965a7bc6ed82669b4ec4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 9 Apr 2020 11:29:52 +0100 Subject: [PATCH 395/459] C++: Base results purely on allocations now, not multiplications by a sizeof. --- .../CWE/CWE-190/TaintedAllocationSize.ql | 6 +- .../TaintedAllocationSize.expected | 116 ------------------ 2 files changed, 1 insertion(+), 121 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 2ed95e6cb55..a4f85ea4a8f 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -16,11 +16,7 @@ import semmle.code.cpp.security.TaintTracking import TaintedWithPath predicate taintedChild(Expr e, Expr tainted) { - ( - isAllocationExpr(e) - or - any(MulExpr me | me.getAChild() instanceof SizeofOperator) = e - ) and + isAllocationExpr(e) and tainted = e.getAChild() and tainted.getUnspecifiedType() instanceof IntegralType } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 4aa02918186..773a969e9ad 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -5,12 +5,6 @@ edges | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | (unsigned long)... | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | (unsigned long)... | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | @@ -33,91 +27,31 @@ edges | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | -| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | (unsigned long)... | -| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | (unsigned long)... | -| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | -| test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | -| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:27 | (unsigned long)... | -| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:27 | size | -| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:27 | size | | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | -| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:27 | (unsigned long)... | -| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:27 | size | -| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:27 | size | | test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... | | test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... | -| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:13 | (unsigned long)... | -| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:13 | size | -| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:13 | size | | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | -| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:13 | (unsigned long)... | -| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:13 | size | -| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:13 | size | | test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... | | test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... | -| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:14 | (unsigned long)... | -| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:14 | size | -| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:14 | size | | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | -| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:14 | (unsigned long)... | -| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:14 | size | -| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:14 | size | | test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | | test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | -| test.cpp:201:9:201:12 | call to atoi | test.cpp:201:9:201:12 | call to atoi | -| test.cpp:201:9:201:12 | call to atoi | test.cpp:201:9:201:28 | (unsigned long)... | -| test.cpp:201:9:201:12 | call to atoi | test.cpp:201:9:201:42 | Store | | test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | | test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | -| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | -| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | -| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | -| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:28 | (unsigned long)... | | test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:42 | Store | -| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:12 | call to atoi | -| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:12 | call to atoi | -| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:12 | call to atoi | -| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:28 | (unsigned long)... | | test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:42 | Store | -| test.cpp:206:13:206:16 | call to atoi | test.cpp:206:13:206:16 | call to atoi | -| test.cpp:206:13:206:16 | call to atoi | test.cpp:206:13:206:32 | (unsigned long)... | -| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | -| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | -| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | -| test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:32 | (unsigned long)... | -| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:16 | call to atoi | -| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:16 | call to atoi | -| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:16 | call to atoi | -| test.cpp:206:18:206:31 | (const char *)... | test.cpp:206:13:206:32 | (unsigned long)... | | test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | | test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | | test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | | test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | -| test.cpp:227:19:227:22 | call to atoi | test.cpp:227:19:227:22 | call to atoi | -| test.cpp:227:19:227:22 | call to atoi | test.cpp:227:19:227:38 | (unsigned long)... | -| test.cpp:227:19:227:22 | call to atoi | test.cpp:229:9:229:18 | (size_t)... | -| test.cpp:227:19:227:22 | call to atoi | test.cpp:229:9:229:18 | local_size | -| test.cpp:227:19:227:22 | call to atoi | test.cpp:229:9:229:18 | local_size | -| test.cpp:227:19:227:22 | call to atoi | test.cpp:235:11:235:20 | (size_t)... | -| test.cpp:227:19:227:22 | call to atoi | test.cpp:237:10:237:19 | (size_t)... | -| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | -| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | -| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | -| test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:38 | (unsigned long)... | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | (size_t)... | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | | test.cpp:227:24:227:29 | call to getenv | test.cpp:235:11:235:20 | (size_t)... | | test.cpp:227:24:227:29 | call to getenv | test.cpp:237:10:237:19 | (size_t)... | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:22 | call to atoi | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:22 | call to atoi | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:22 | call to atoi | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:227:19:227:38 | (unsigned long)... | | test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | (size_t)... | | test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | | test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | @@ -133,11 +67,6 @@ nodes | test.cpp:42:38:42:44 | tainted | semmle.label | tainted | | test.cpp:42:38:42:44 | tainted | semmle.label | tainted | | test.cpp:42:38:42:44 | tainted | semmle.label | tainted | -| test.cpp:43:38:43:44 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:43:38:43:44 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:43:38:43:44 | tainted | semmle.label | tainted | -| test.cpp:43:38:43:44 | tainted | semmle.label | tainted | -| test.cpp:43:38:43:44 | tainted | semmle.label | tainted | | test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | | test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | | test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | @@ -155,56 +84,24 @@ nodes | test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | | test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | | test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | -| test.cpp:52:54:52:60 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:52:54:52:60 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:52:54:52:60 | tainted | semmle.label | tainted | -| test.cpp:52:54:52:60 | tainted | semmle.label | tainted | -| test.cpp:52:54:52:60 | tainted | semmle.label | tainted | | test.cpp:123:18:123:23 | call to getenv | semmle.label | call to getenv | | test.cpp:123:18:123:31 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:127:24:127:27 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:127:24:127:27 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:127:24:127:27 | size | semmle.label | size | -| test.cpp:127:24:127:27 | size | semmle.label | size | -| test.cpp:127:24:127:27 | size | semmle.label | size | | test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | | test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | | test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | | test.cpp:132:19:132:24 | call to getenv | semmle.label | call to getenv | | test.cpp:132:19:132:32 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:134:10:134:13 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:134:10:134:13 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:134:10:134:13 | size | semmle.label | size | -| test.cpp:134:10:134:13 | size | semmle.label | size | -| test.cpp:134:10:134:13 | size | semmle.label | size | | test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | | test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | | test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | | test.cpp:138:19:138:24 | call to getenv | semmle.label | call to getenv | | test.cpp:138:19:138:32 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:142:11:142:14 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:142:11:142:14 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:142:11:142:14 | size | semmle.label | size | -| test.cpp:142:11:142:14 | size | semmle.label | size | -| test.cpp:142:11:142:14 | size | semmle.label | size | | test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | | test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | | test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | -| test.cpp:201:9:201:12 | call to atoi | semmle.label | call to atoi | -| test.cpp:201:9:201:12 | call to atoi | semmle.label | call to atoi | -| test.cpp:201:9:201:12 | call to atoi | semmle.label | call to atoi | -| test.cpp:201:9:201:28 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:201:9:201:28 | (unsigned long)... | semmle.label | (unsigned long)... | | test.cpp:201:9:201:42 | Store | semmle.label | Store | | test.cpp:201:14:201:19 | call to getenv | semmle.label | call to getenv | | test.cpp:201:14:201:27 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:206:13:206:16 | call to atoi | semmle.label | call to atoi | -| test.cpp:206:13:206:16 | call to atoi | semmle.label | call to atoi | -| test.cpp:206:13:206:16 | call to atoi | semmle.label | call to atoi | -| test.cpp:206:13:206:32 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:206:13:206:32 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:206:18:206:23 | call to getenv | semmle.label | call to getenv | -| test.cpp:206:18:206:31 | (const char *)... | semmle.label | (const char *)... | | test.cpp:214:23:214:23 | s | semmle.label | s | | test.cpp:215:21:215:21 | s | semmle.label | s | | test.cpp:215:21:215:21 | s | semmle.label | s | @@ -213,11 +110,6 @@ nodes | test.cpp:221:21:221:21 | s | semmle.label | s | | test.cpp:221:21:221:21 | s | semmle.label | s | | test.cpp:221:21:221:21 | s | semmle.label | s | -| test.cpp:227:19:227:22 | call to atoi | semmle.label | call to atoi | -| test.cpp:227:19:227:22 | call to atoi | semmle.label | call to atoi | -| test.cpp:227:19:227:22 | call to atoi | semmle.label | call to atoi | -| test.cpp:227:19:227:38 | (unsigned long)... | semmle.label | (unsigned long)... | -| test.cpp:227:19:227:38 | (unsigned long)... | semmle.label | (unsigned long)... | | test.cpp:227:24:227:29 | call to getenv | semmle.label | call to getenv | | test.cpp:227:24:227:37 | (const char *)... | semmle.label | (const char *)... | | test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | @@ -233,22 +125,14 @@ nodes #select | test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:43:38:43:63 | ... * ... | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:48:25:48:30 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:52:35:52:60 | ... * ... | test.cpp:39:21:39:24 | argv | test.cpp:52:54:52:60 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | | test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | -| test.cpp:127:24:127:41 | ... * ... | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:27 | size | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | | test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | -| test.cpp:134:10:134:27 | ... * ... | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:13 | size | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | | test.cpp:142:4:142:9 | call to malloc | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | -| test.cpp:142:11:142:28 | ... * ... | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:14 | size | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | -| test.cpp:201:9:201:42 | ... * ... | test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:12 | call to atoi | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) | -| test.cpp:206:13:206:46 | ... * ... | test.cpp:206:18:206:23 | call to getenv | test.cpp:206:13:206:16 | call to atoi | This allocation size is derived from $@ and might overflow | test.cpp:206:18:206:23 | call to getenv | user input (getenv) | | test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | | test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | -| test.cpp:227:19:227:52 | ... * ... | test.cpp:227:24:227:29 | call to getenv | test.cpp:227:19:227:22 | call to atoi | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | | test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | | test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) | From ba3a8d0872461e7106152ab377b52a3413a274cf Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 9 Apr 2020 13:10:22 +0100 Subject: [PATCH 396/459] C++: Improve naming and QLDoc. --- .../CWE/CWE-190/TaintedAllocationSize.ql | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index a4f85ea4a8f..54c6d1e7a96 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -15,27 +15,31 @@ import cpp import semmle.code.cpp.security.TaintTracking import TaintedWithPath -predicate taintedChild(Expr e, Expr tainted) { - isAllocationExpr(e) and - tainted = e.getAChild() and +/** + * Holds if `alloc` is an allocation, and `tainted` is a child of it that is a + * taint sink. + */ +predicate allocSink(Expr alloc, Expr tainted) { + isAllocationExpr(alloc) and + tainted = alloc.getAChild() and tainted.getUnspecifiedType() instanceof IntegralType } class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration { - override predicate isSink(Element tainted) { taintedChild(_, tainted) } + override predicate isSink(Element tainted) { allocSink(_, tainted) } } predicate taintedAllocSize( - Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause + Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause ) { isUserInput(source, taintCause) and exists(Expr tainted | - taintedChild(e, tainted) and + allocSink(alloc, tainted) and taintedWithPath(source, tainted, sourceNode, sinkNode) ) } -from Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause -where taintedAllocSize(e, source, sourceNode, sinkNode, taintCause) -select e, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow", +from Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause +where taintedAllocSize(source, alloc, sourceNode, sinkNode, taintCause) +select alloc, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow", source, "user input (" + taintCause + ")" From 7a586c97a46e64a307af8eb872d7f542c0f3a89a Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Apr 2020 14:30:40 -0700 Subject: [PATCH 397/459] Python: ObjectAPI to ValueAPI: IterReturnsNonIterature: Replaces custom return_type predicate with call to getAnInferredReturnType --- python/ql/src/Functions/IterReturnsNonIterator.ql | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/python/ql/src/Functions/IterReturnsNonIterator.ql b/python/ql/src/Functions/IterReturnsNonIterator.ql index 20e3d311fa8..405bff78c04 100644 --- a/python/ql/src/Functions/IterReturnsNonIterator.ql +++ b/python/ql/src/Functions/IterReturnsNonIterator.ql @@ -12,18 +12,10 @@ import python -ClassValue return_type(FunctionValue f) { - exists(ControlFlowNode n, Return ret | - ret.getScope() = f.getScope() and - ret.getValue() = n.getNode() and - result = n.pointsTo().getClass() - ) -} - from ClassValue iterable, FunctionValue iter, ClassValue iterator where iter = iterable.lookup("__iter__") and - iterator = return_type(iter) and + iterator = iter.getAnInferredReturnType() and not iterator.isIterator() select iterator, "Class " + iterator.getName() + From 336e48c5c64f78dcf662854e6c3eb1758d349d3d Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Apr 2020 14:50:26 -0700 Subject: [PATCH 398/459] Python: ObjectAPI to ValueAPI: IncorrectlySpecifiedOverriddenMethod: Adds preliminary modernization --- .../IncorrectlySpecifiedOverriddenMethod.ql | 12 +++++----- .../src/semmle/python/objects/ObjectAPI.qll | 24 +++++++++++++++++++ ...orrectlySpecifiedOverriddenMethod.expected | 18 +++++++------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql index 0dd0fd5856b..66ea5e43831 100644 --- a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql +++ b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql @@ -13,21 +13,21 @@ import python import Expressions.CallArgs -from Call call, FunctionObject func, FunctionObject overriding, string problem +from Call call, FunctionValue func, FunctionValue overriding, string problem where not func.getName() = "__init__" and overriding.overrides(func) and call = overriding.getAMethodCall().getNode() and - correct_args_if_called_as_method_objectapi(call, overriding) and + correct_args_if_called_as_method(call, overriding) and ( - arg_count_objectapi(call) + 1 < func.minParameters() and problem = "too few arguments" + arg_count(call) + 1 < func.minParameters() and problem = "too few arguments" or - arg_count_objectapi(call) >= func.maxParameters() and problem = "too many arguments" + arg_count(call) >= func.maxParameters() and problem = "too many arguments" or exists(string name | call.getAKeyword().getArg() = name and - overriding.getFunction().getAnArg().(Name).getId() = name and - not func.getFunction().getAnArg().(Name).getId() = name and + overriding.getScope().getAnArg().(Name).getId() = name and + not func.getScope().getAnArg().(Name).getId() = name and problem = "an argument named '" + name + "'" ) ) diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 9772a77ed8b..0763bd1ba77 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -573,6 +573,9 @@ class ClassValue extends Value { abstract class FunctionValue extends CallableValue { abstract string getQualifiedName(); + /** Gets a longer, more descriptive version of toString() */ + abstract string descriptiveString(); + /** Gets the minimum number of parameters that can be correctly passed to this function */ abstract int minParameters(); @@ -605,6 +608,14 @@ abstract class FunctionValue extends CallableValue { ) } + /** Gets a call-site from where this function is called as a method */ + CallNode getAMethodCall() { + exists(BoundMethodObjectInternal bm | + result.getFunction().pointsTo() = bm and + bm.getFunction() = this + ) + } + /** Gets a class that this function may return */ abstract ClassValue getAnInferredReturnType(); } @@ -617,6 +628,15 @@ class PythonFunctionValue extends FunctionValue { result = this.(PythonFunctionObjectInternal).getScope().getQualifiedName() } + override string descriptiveString() { + if this.getScope().isMethod() + then + exists(Class cls | this.getScope().getScope() = cls | + result = "method " + this.getQualifiedName() + ) + else result = "function " + this.getQualifiedName() + } + override int minParameters() { exists(Function f | f = this.getScope() and @@ -650,6 +670,8 @@ class BuiltinFunctionValue extends FunctionValue { override string getQualifiedName() { result = this.(BuiltinFunctionObjectInternal).getName() } + override string descriptiveString() { result = "builtin-function " + this.getName() } + override int minParameters() { none() } override int maxParameters() { none() } @@ -674,6 +696,8 @@ class BuiltinMethodValue extends FunctionValue { ) } + override string descriptiveString() { result = "builtin-method " + this.getQualifiedName() } + override int minParameters() { none() } override int maxParameters() { none() } diff --git a/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected b/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected index 527ad805604..3192999aad2 100644 --- a/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected +++ b/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected @@ -1,9 +1,9 @@ -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:16:9:16:21 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:35:9:35:21 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:8:5:8:26 | Function meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:17:9:17:20 | Attribute() | call | test.py:27:5:27:20 | Function meth2 | method Derived.meth2 | -| test.py:8:5:8:26 | Function meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:36:9:36:20 | Attribute() | call | test.py:27:5:27:20 | Function meth2 | method Derived.meth2 | -| test.py:64:5:64:19 | Function meth | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:78:1:78:12 | Attribute() | call | test.py:74:5:74:24 | Function meth | method Correct2.meth | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:16:9:16:21 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:35:9:35:21 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:8:5:8:26 | Function Base.meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:17:9:17:20 | Attribute() | call | test.py:27:5:27:20 | Function Derived.meth2 | method Derived.meth2 | +| test.py:8:5:8:26 | Function Base.meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:36:9:36:20 | Attribute() | call | test.py:27:5:27:20 | Function Derived.meth2 | method Derived.meth2 | +| test.py:64:5:64:19 | Function BlameBase.meth | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:78:1:78:12 | Attribute() | call | test.py:74:5:74:24 | Function Correct2.meth | method Correct2.meth | From 8dc1933a021aea77210af672d8409cace5ac998d Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Apr 2020 14:58:30 -0700 Subject: [PATCH 399/459] Python: ObjectAPI to ValueAPI: WrongNumberArgumentsInClassInstantiation: Adds preliminary modernization --- ...rongNumberArgumentsInClassInstantiation.ql | 8 ++--- ...mberArgumentsInClassInstantiation.expected | 30 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql index f04d2350855..c8763bd8aa7 100644 --- a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql @@ -15,17 +15,17 @@ import python import Expressions.CallArgs -from Call call, ClassObject cls, string too, string should, int limit, FunctionObject init +from Call call, ClassValue cls, string too, string should, int limit, FunctionValue init where ( - too_many_args_objectapi(call, cls, limit) and + too_many_args(call, cls, limit) and too = "too many arguments" and should = "no more than " or - too_few_args_objectapi(call, cls, limit) and + too_few_args(call, cls, limit) and too = "too few arguments" and should = "no fewer than " ) and - init = get_function_or_initializer_objectapi(cls) + init = get_function_or_initializer(cls) select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", init, init.getQualifiedName() diff --git a/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected b/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected index b0c156dc867..f0df1fe58c9 100644 --- a/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected +++ b/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected @@ -1,15 +1,15 @@ -| wrong_arguments.py:37:1:37:4 | F0() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:4:5:4:26 | Function __init__ | F0.__init__ | -| wrong_arguments.py:38:1:38:4 | F1() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:8:5:8:36 | Function __init__ | F1.__init__ | -| wrong_arguments.py:39:1:39:4 | F2() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:12:5:12:30 | Function __init__ | F2.__init__ | -| wrong_arguments.py:40:1:40:4 | F3() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:16:5:16:40 | Function __init__ | F3.__init__ | -| wrong_arguments.py:41:1:41:4 | F4() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:20:5:20:31 | Function __init__ | F4.__init__ | -| wrong_arguments.py:42:1:42:4 | F5() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:24:5:24:42 | Function __init__ | F5.__init__ | -| wrong_arguments.py:43:1:43:5 | F6() | Call to $@ with too few arguments; should be no fewer than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:44:1:44:7 | F7() | Call to $@ with too few arguments; should be no fewer than 3. | wrong_arguments.py:32:5:32:33 | Function __init__ | F7.__init__ | -| wrong_arguments.py:48:1:48:7 | F0() | Call to $@ with too many arguments; should be no more than 1. | wrong_arguments.py:4:5:4:26 | Function __init__ | F0.__init__ | -| wrong_arguments.py:49:1:49:9 | F1() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:8:5:8:36 | Function __init__ | F1.__init__ | -| wrong_arguments.py:50:1:50:9 | F5() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:24:5:24:42 | Function __init__ | F5.__init__ | -| wrong_arguments.py:51:1:51:9 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:52:1:52:11 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:85:1:85:12 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:86:1:86:7 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | +| wrong_arguments.py:37:1:37:4 | F0() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:4:5:4:26 | Function F0.__init__ | F0.__init__ | +| wrong_arguments.py:38:1:38:4 | F1() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:8:5:8:36 | Function F1.__init__ | F1.__init__ | +| wrong_arguments.py:39:1:39:4 | F2() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:12:5:12:30 | Function F2.__init__ | F2.__init__ | +| wrong_arguments.py:40:1:40:4 | F3() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:16:5:16:40 | Function F3.__init__ | F3.__init__ | +| wrong_arguments.py:41:1:41:4 | F4() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:20:5:20:31 | Function F4.__init__ | F4.__init__ | +| wrong_arguments.py:42:1:42:4 | F5() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:24:5:24:42 | Function F5.__init__ | F5.__init__ | +| wrong_arguments.py:43:1:43:5 | F6() | Call to $@ with too few arguments; should be no fewer than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:44:1:44:7 | F7() | Call to $@ with too few arguments; should be no fewer than 3. | wrong_arguments.py:32:5:32:33 | Function F7.__init__ | F7.__init__ | +| wrong_arguments.py:48:1:48:7 | F0() | Call to $@ with too many arguments; should be no more than 1. | wrong_arguments.py:4:5:4:26 | Function F0.__init__ | F0.__init__ | +| wrong_arguments.py:49:1:49:9 | F1() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:8:5:8:36 | Function F1.__init__ | F1.__init__ | +| wrong_arguments.py:50:1:50:9 | F5() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:24:5:24:42 | Function F5.__init__ | F5.__init__ | +| wrong_arguments.py:51:1:51:9 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:52:1:52:11 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:85:1:85:12 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:86:1:86:7 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | From 339758fa70465859710d21f1cc5172e279f8d58e Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Apr 2020 15:04:44 -0700 Subject: [PATCH 400/459] Python: ObjectAPI to ValueAPI: WrongNameForArgumentInClassInstantiation: Adds preliminary modernization --- .../Classes/WrongNameForArgumentInClassInstantiation.ql | 6 +++--- .../WrongNameForArgumentInClassInstantiation.expected | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql index 3ac4454a019..f3276ac61ef 100644 --- a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql @@ -16,9 +16,9 @@ import python import Expressions.CallArgs -from Call call, ClassObject cls, string name, FunctionObject init +from Call call, ClassValue cls, string name, FunctionValue init where - illegally_named_parameter_objectapi(call, cls, name) and - init = get_function_or_initializer_objectapi(cls) + illegally_named_parameter(call, cls, name) and + init = get_function_or_initializer(cls) select call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", init, init.getQualifiedName() diff --git a/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected b/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected index cf89ddfc44f..4bdb1134776 100644 --- a/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected +++ b/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected @@ -1,4 +1,4 @@ -| wrong_arguments.py:65:1:65:7 | F0() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:4:5:4:26 | Function __init__ | F0.__init__ | -| wrong_arguments.py:66:1:66:7 | F1() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:8:5:8:36 | Function __init__ | F1.__init__ | -| wrong_arguments.py:67:1:67:12 | F2() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:12:5:12:30 | Function __init__ | F2.__init__ | -| wrong_arguments.py:92:1:92:27 | F6() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | +| wrong_arguments.py:65:1:65:7 | F0() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:4:5:4:26 | Function F0.__init__ | F0.__init__ | +| wrong_arguments.py:66:1:66:7 | F1() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:8:5:8:36 | Function F1.__init__ | F1.__init__ | +| wrong_arguments.py:67:1:67:12 | F2() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:12:5:12:30 | Function F2.__init__ | F2.__init__ | +| wrong_arguments.py:92:1:92:27 | F6() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | From 8e91f100306d1e475bdc49ffb8ba4ffd1473faff Mon Sep 17 00:00:00 2001 From: Rebecca Valentine Date: Thu, 9 Apr 2020 15:25:38 -0700 Subject: [PATCH 401/459] Python: ObjectAPI to ValueAPI: UselessClass: Adds preliminary modernization --- python/ql/src/Classes/UselessClass.ql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/src/Classes/UselessClass.ql b/python/ql/src/Classes/UselessClass.ql index 2c872420049..e4e3f31f3a2 100644 --- a/python/ql/src/Classes/UselessClass.ql +++ b/python/ql/src/Classes/UselessClass.ql @@ -22,9 +22,9 @@ predicate does_not_define_special_method(Class cls) { } predicate no_inheritance(Class c) { - not exists(ClassObject cls, ClassObject other | - cls.getPyClass() = c and - other != theObjectType() + not exists(ClassValue cls, ClassValue other | + cls.getScope() = c and + other != ClassValue::object() | other.getABaseType() = cls or cls.getABaseType() = other From 945ecffd05da4580abee5df56a65f399f86c50c4 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 13 Apr 2020 14:18:57 +0200 Subject: [PATCH 402/459] C++: Add charpred to ParameterNode --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index cec0ae1d138..cfe1196d5e9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -162,6 +162,12 @@ class ExprNode extends InstructionNode { * as `x` in `f(x)` and implicit parameters such as `this` in `x.f()` */ class ParameterNode extends InstructionNode { + ParameterNode() { + instr instanceof InitializeParameterInstruction + or + instr instanceof InitializeThisInstruction + } + /** * Holds if this node is the parameter of `c` at the specified (zero-based) * position. The implicit `this` parameter is considered to have index `-1`. From cde34c9b1b284bb587eae31d151f04da15fbce5f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 13 Apr 2020 16:19:21 +0200 Subject: [PATCH 403/459] C++: Accept test output which I previously forgot to accept --- .../dataflow/fields/ir-flow.expected | 81 +++++++------------ .../literals/literals/literals.expected | 8 +- .../CWE-134/semmle/funcs/funcsLocal.expected | 8 -- 3 files changed, 34 insertions(+), 63 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index 6d34e81e849..15a6d699adb 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -1,62 +1,41 @@ edges -| aliasing.cpp:37:3:37:24 | Store : void | aliasing.cpp:38:11:38:12 | m1 | -| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | Store : void | -| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | -| aliasing.cpp:42:3:42:22 | Store : void | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | Store : void | -| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:60:3:60:22 | Chi [m1] : void | aliasing.cpp:61:13:61:14 | Store [m1] : void | -| aliasing.cpp:60:3:60:22 | Store : void | aliasing.cpp:60:3:60:22 | Chi [m1] : void | -| aliasing.cpp:60:11:60:20 | call to user_input : void | aliasing.cpp:60:3:60:22 | Store : void | -| aliasing.cpp:61:13:61:14 | Store [m1] : void | aliasing.cpp:62:14:62:15 | m1 | -| aliasing.cpp:79:3:79:22 | Store : void | aliasing.cpp:80:12:80:13 | m1 | -| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | Store : void | -| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | -| aliasing.cpp:86:3:86:21 | Store : void | aliasing.cpp:87:12:87:13 | m1 | -| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | Store : void | -| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | -| aliasing.cpp:92:3:92:23 | Store : void | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | Store : void | -| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | -| struct_init.c:20:20:20:29 | Store : void | struct_init.c:22:11:22:11 | a | -| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | Store : void | -| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | -| struct_init.c:27:7:27:16 | Store : void | struct_init.c:31:23:31:23 | a | -| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | Store : void | -| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | +| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] | +| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] | +| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store | +| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 | +| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | +| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | +| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | nodes -| aliasing.cpp:37:3:37:24 | Store : void | semmle.label | Store : void | -| aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | -| aliasing.cpp:42:3:42:22 | Store : void | semmle.label | Store : void | -| aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | -| aliasing.cpp:60:3:60:22 | Chi [m1] : void | semmle.label | Chi [m1] : void | -| aliasing.cpp:60:3:60:22 | Store : void | semmle.label | Store : void | -| aliasing.cpp:60:11:60:20 | call to user_input : void | semmle.label | call to user_input : void | -| aliasing.cpp:61:13:61:14 | Store [m1] : void | semmle.label | Store [m1] : void | +| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:60:3:60:22 | Store | semmle.label | Store | +| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] | | aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 | -| aliasing.cpp:79:3:79:22 | Store : void | semmle.label | Store : void | -| aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:79:11:79:20 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | -| aliasing.cpp:86:3:86:21 | Store : void | semmle.label | Store : void | -| aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:86:10:86:19 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | -| aliasing.cpp:92:3:92:23 | Store : void | semmle.label | Store : void | -| aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void | +| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | -| struct_init.c:20:20:20:29 | Store : void | semmle.label | Store : void | -| struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void | +| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input | | struct_init.c:22:11:22:11 | a | semmle.label | a | -| struct_init.c:27:7:27:16 | Store : void | semmle.label | Store : void | -| struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void | +| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | | struct_init.c:31:23:31:23 | a | semmle.label | a | #select -| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void | -| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input : void | call to user_input : void | -| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input : void | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input : void | call to user_input : void | -| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input : void | call to user_input : void | -| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input : void | call to user_input : void | -| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input : void | call to user_input : void | -| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input : void | call to user_input : void | -| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input : void | call to user_input : void | +| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input | call to user_input | +| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input | call to user_input | +| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input | +| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input | call to user_input | +| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input | call to user_input | +| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input | +| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input | +| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/literals/literals/literals.expected b/cpp/ql/test/library-tests/literals/literals/literals.expected index 4e640c9b2dc..a3fd43a7f04 100644 --- a/cpp/ql/test/library-tests/literals/literals/literals.expected +++ b/cpp/ql/test/library-tests/literals/literals/literals.expected @@ -2,10 +2,10 @@ | literals.c:3:13:3:16 | 1.0 | | literals.c:4:13:4:16 | 1.0 | | literals.c:5:13:5:16 | 1.0 | -| literals.c:6:13:6:16 | (1.0,1.0i) | -| literals.c:7:13:7:16 | (1.0,1.0i) | -| literals.c:8:13:8:16 | (1.0,1.0i) | -| literals.c:9:13:9:16 | (1.0,1.0i) | +| literals.c:6:13:6:16 | (0.0,1.0i) | +| literals.c:7:13:7:16 | (0.0,1.0i) | +| literals.c:8:13:8:16 | (0.0,1.0i) | +| literals.c:9:13:9:16 | (0.0,1.0i) | | literals.c:10:13:10:16 | 1.0 | | literals.c:11:13:11:16 | 1.0 | | literals.c:12:13:12:16 | 1.0 | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 1ccd19e1ad9..a05e392ecf2 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -17,14 +17,10 @@ edges | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | (const char *)... | | funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | (const char *)... | | funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:32:9:32:10 | (const char *)... | -| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | (const char *)... | | funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 | | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | (const char *)... | @@ -35,14 +31,10 @@ edges | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | -| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | -| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | (const char *)... | | funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | (const char *)... | | funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | -| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:42:9:42:10 | (const char *)... | -| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:42:9:42:10 | i6 | nodes | funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument | | funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 | From 87791778393533ff59b6971cf49f7846fb846174 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 13 Apr 2020 14:03:02 -0700 Subject: [PATCH 404/459] C++: accept minor test change --- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 64faf3331ad..10ec2a63dc2 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6523,7 +6523,7 @@ ir.cpp: # 1262| r1262_5(glval) = FieldAddress[member] : r1262_4 # 1262| mu1262_6(int) = Store : &:r1262_5, r1262_2 # 1263| v1263_1(void) = NoOp : -# 1261| v1261_11(void) = ReturnIndirection : &:r1261_7, ~mu1261_4 +# 1261| v1261_11(void) = ReturnIndirection[a] : &:r1261_7, ~mu1261_4 # 1261| v1261_12(void) = ReturnVoid : # 1261| v1261_13(void) = UnmodeledUse : mu* # 1261| v1261_14(void) = AliasedUse : ~mu1261_4 @@ -6625,7 +6625,7 @@ ir.cpp: # 1286| v1286_5(void) = Call : func:r1286_4 # 1286| mu1286_6(unknown) = ^CallSideEffect : ~mu1270_4 # 1287| v1287_1(void) = NoOp : -# 1270| v1270_11(void) = ReturnIndirection : &:r1270_9, ~mu1270_4 +# 1270| v1270_11(void) = ReturnIndirection[a_arg] : &:r1270_9, ~mu1270_4 # 1270| v1270_12(void) = ReturnVoid : # 1270| v1270_13(void) = UnmodeledUse : mu* # 1270| v1270_14(void) = AliasedUse : ~mu1270_4 From de29d93edeb6a19d7debdebf4a8fc8848d58eee3 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 13 Apr 2020 14:39:51 -0700 Subject: [PATCH 405/459] C++: add method qldoc for Comment.qll --- cpp/ql/src/semmle/code/cpp/Comments.qll | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Comments.qll b/cpp/ql/src/semmle/code/cpp/Comments.qll index e517f8e7b0e..1558bf95477 100644 --- a/cpp/ql/src/semmle/code/cpp/Comments.qll +++ b/cpp/ql/src/semmle/code/cpp/Comments.qll @@ -1,3 +1,5 @@ + + import semmle.code.cpp.Location import semmle.code.cpp.Element @@ -13,8 +15,20 @@ class Comment extends Locatable, @comment { override Location getLocation() { comments(underlyingElement(this), _, result) } + /** + * Gets the text of this comment, including the opening `//` or `/*`, and the closing `*``/` if + * present. + */ string getContents() { comments(underlyingElement(this), result, _) } + /** + * Gets the AST element this comment is associated with. For example, the comment in the + * following code is associated with the declaration of `j`. + * ``` + * int i; + * int j; // Comment on j + * ``` + */ Element getCommentedElement() { commentbinding(underlyingElement(this), unresolveElement(result)) } From d065389a6b082c675aba0da941d09a92249791bd Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 13 Apr 2020 14:41:25 -0700 Subject: [PATCH 406/459] C++: add method commetns in Compilation.qll --- cpp/ql/src/semmle/code/cpp/Compilation.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/src/semmle/code/cpp/Compilation.qll b/cpp/ql/src/semmle/code/cpp/Compilation.qll index 02d962844c8..42c2009a751 100644 --- a/cpp/ql/src/semmle/code/cpp/Compilation.qll +++ b/cpp/ql/src/semmle/code/cpp/Compilation.qll @@ -40,6 +40,7 @@ class Compilation extends @compilation { /** Gets a file compiled during this invocation. */ File getAFileCompiled() { result = getFileCompiled(_) } + /** Gets the `i`th file compiled during this invocation */ File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) } /** From f24c4e51c51a10f2b55115663f8fd043b728555c Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 13 Apr 2020 14:58:30 -0700 Subject: [PATCH 407/459] C++: add method qldoc in Diagnostics.qll --- cpp/ql/src/semmle/code/cpp/Diagnostics.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/src/semmle/code/cpp/Diagnostics.qll b/cpp/ql/src/semmle/code/cpp/Diagnostics.qll index f03f03783c1..37459602c03 100644 --- a/cpp/ql/src/semmle/code/cpp/Diagnostics.qll +++ b/cpp/ql/src/semmle/code/cpp/Diagnostics.qll @@ -11,6 +11,7 @@ class Diagnostic extends Locatable, @diagnostic { /** Gets the error code for this compiler message. */ string getTag() { diagnostics(underlyingElement(this), _, result, _, _, _) } + /** Holds if `s` is the error code for this compiler message. */ predicate hasTag(string s) { this.getTag() = s } /** From 603a3af19b62b2f171ec4d34f8bc56250578b434 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Mon, 13 Apr 2020 18:09:44 -0400 Subject: [PATCH 408/459] C++: Treat implicit end of body of non`-void` function as `Unreached` When the extractor can't prove that control flow will never reach the end of a non-`void`-returning function without reaching an explicit `return` statement, it inserts an implicit `return` without an operand. If control actually reaches this point, the behavior is undefined. We were previously generating invalid IR for these implicit `return` statements, because the lack of an operand meant that there was no definition of the return value variable along that path. Instead, I've changed the IR generation to emit an `Unreached` instruction for the implicit `return`. This ensures that we don't create a control flow edge from the end of the body to the function epilogue. The change to the range analysis test avoids having that test depend on the previous bad IR behavior, while still preserving the original spirit of the test. --- .../raw/internal/TranslatedFunction.qll | 7 +++- .../raw/internal/TranslatedStmt.qll | 38 ++++++++++++++++++- .../library-tests/ir/ir/PrintAST.expected | 17 +++++++++ cpp/ql/test/library-tests/ir/ir/ir.cpp | 12 ++++-- .../test/library-tests/ir/ir/raw_ir.expected | 30 +++++++++++++++ .../rangeanalysis/RangeAnalysis.expected | 2 +- .../rangeanalysis/rangeanalysis/test.cpp | 8 ++-- 7 files changed, 104 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 1bfc1c8275f..c93562c1390 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -49,6 +49,11 @@ CppType getEllipsisVariablePRValueType() { CppType getEllipsisVariableGLValueType() { result = getTypeForGLValue(any(UnknownType t)) } +/** + * Holds if the function returns a value, as opposed to returning `void`. + */ +predicate hasReturnValue(Function func) { not func.getUnspecifiedType() instanceof VoidType } + /** * Represents the IR translation of a function. This is the root elements for * all other elements associated with this function. @@ -312,7 +317,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { /** * Holds if the function has a non-`void` return type. */ - final predicate hasReturnValue() { not func.getUnspecifiedType() instanceof VoidType } + final predicate hasReturnValue() { hasReturnValue(func) } /** * Gets the single `UnmodeledDefinition` instruction for this function. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index 88a7d4c99ea..f7d060c7c64 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -131,6 +131,9 @@ abstract class TranslatedReturnStmt extends TranslatedStmt { } } +/** + * The IR translation of a `return` statement that returns a value. + */ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariableInitialization { TranslatedReturnValueStmt() { stmt.hasExpr() } @@ -147,8 +150,14 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() } } +/** + * The IR translation of a `return` statement that does not return a value. This includes implicit + * return statements at the end of `void`-returning functions. + */ class TranslatedReturnVoidStmt extends TranslatedReturnStmt { - TranslatedReturnVoidStmt() { not stmt.hasExpr() } + TranslatedReturnVoidStmt() { + not stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction()) + } override TranslatedElement getChild(int id) { none() } @@ -169,6 +178,33 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt { override Instruction getChildSuccessor(TranslatedElement child) { none() } } +/** + * The IR translation of an implicit `return` statement generated by the extractor to handle control + * flow that reaches the end of a non-`void`-returning function body. Since such control flow + * produces undefined behavior, we simply generate an `Unreached` instruction to prevent that flow + * from continuing on to pollute other analysis. The assumption is that the developer is certain + * that the implicit `return` is unreachable, even if the compiler cannot prove it. + */ +class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt { + TranslatedUnreachableReturnStmt() { + not stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) + } + + override TranslatedElement getChild(int id) { none() } + + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::Unreached and + resultType = getVoidType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } + + override Instruction getChildSuccessor(TranslatedElement child) { none() } +} + /** * The IR translation of a C++ `try` statement. */ diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index e218b6daf47..e2a02352f0f 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -8750,6 +8750,23 @@ ir.cpp: # 1286| Type = [PointerType] A * # 1286| ValueCategory = prvalue # 1287| 12: [ReturnStmt] return ... +# 1289| [TopLevelFunction] int missingReturnValue(bool, int) +# 1289| params: +# 1289| 0: [Parameter] b +# 1289| Type = [BoolType] bool +# 1289| 1: [Parameter] x +# 1289| Type = [IntType] int +# 1289| body: [Block] { ... } +# 1290| 0: [IfStmt] if (...) ... +# 1290| 0: [VariableAccess] b +# 1290| Type = [BoolType] bool +# 1290| ValueCategory = prvalue(load) +# 1290| 1: [Block] { ... } +# 1291| 0: [ReturnStmt] return ... +# 1291| 0: [VariableAccess] x +# 1291| Type = [IntType] int +# 1291| ValueCategory = prvalue(load) +# 1293| 1: [ReturnStmt] return ... perf-regression.cpp: # 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&) # 4| params: diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index ec40d944789..e40c4c095d6 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1249,10 +1249,10 @@ char *strcpy(char *destination, const char *source); char *strcat(char *destination, const char *source); void test_strings(char *s1, char *s2) { - char buffer[1024] = {0}; + char buffer[1024] = {0}; - strcpy(buffer, s1); - strcat(buffer, s2); + strcpy(buffer, s1); + strcat(buffer, s2); } struct A { @@ -1286,4 +1286,10 @@ void test_static_member_functions(int int_arg, A* a_arg) { getAnInstanceOfA()->static_member_without_def(); } +int missingReturnValue(bool b, int x) { + if (b) { + return x; + } +} + // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index d74ce2920b0..344269ec7db 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6631,6 +6631,36 @@ ir.cpp: # 1270| v1270_14(void) = AliasedUse : ~mu1270_4 # 1270| v1270_15(void) = ExitFunction : +# 1289| int missingReturnValue(bool, int) +# 1289| Block 0 +# 1289| v1289_1(void) = EnterFunction : +# 1289| mu1289_2(unknown) = AliasedDefinition : +# 1289| mu1289_3(unknown) = InitializeNonLocal : +# 1289| mu1289_4(unknown) = UnmodeledDefinition : +# 1289| r1289_5(glval) = VariableAddress[b] : +# 1289| mu1289_6(bool) = InitializeParameter[b] : &:r1289_5 +# 1289| r1289_7(glval) = VariableAddress[x] : +# 1289| mu1289_8(int) = InitializeParameter[x] : &:r1289_7 +# 1290| r1290_1(glval) = VariableAddress[b] : +# 1290| r1290_2(bool) = Load : &:r1290_1, ~mu1289_4 +# 1290| v1290_3(void) = ConditionalBranch : r1290_2 +#-----| False -> Block 1 +#-----| True -> Block 2 + +# 1293| Block 1 +# 1293| v1293_1(void) = Unreached : + +# 1291| Block 2 +# 1291| r1291_1(glval) = VariableAddress[#return] : +# 1291| r1291_2(glval) = VariableAddress[x] : +# 1291| r1291_3(int) = Load : &:r1291_2, ~mu1289_4 +# 1291| mu1291_4(int) = Store : &:r1291_1, r1291_3 +# 1289| r1289_9(glval) = VariableAddress[#return] : +# 1289| v1289_10(void) = ReturnValue : &:r1289_9, ~mu1289_4 +# 1289| v1289_11(void) = UnmodeledUse : mu* +# 1289| v1289_12(void) = AliasedUse : ~mu1289_4 +# 1289| v1289_13(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0 diff --git a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected index be768a4a82f..78ff3edde3d 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected @@ -35,7 +35,7 @@ | test.cpp:97:10:97:10 | Load: x | file://:0:0:0:0 | 0 | 1 | false | CompareLT: ... < ... | test.cpp:94:7:94:11 | test.cpp:94:7:94:11 | | test.cpp:100:10:100:10 | Load: x | file://:0:0:0:0 | 0 | 1 | true | CompareLE: ... <= ... | test.cpp:99:7:99:12 | test.cpp:99:7:99:12 | | test.cpp:102:10:102:10 | Load: x | file://:0:0:0:0 | 0 | 2 | false | CompareLE: ... <= ... | test.cpp:99:7:99:12 | test.cpp:99:7:99:12 | -| test.cpp:107:5:107:10 | Phi: test10 | test.cpp:114:3:114:6 | Phi: call to sink | -1 | true | CompareLT: ... < ... | test.cpp:115:18:115:22 | test.cpp:115:18:115:22 | +| test.cpp:117:10:117:10 | Load: i | test.cpp:114:3:114:6 | Phi: call to sink | -1 | true | CompareLT: ... < ... | test.cpp:116:7:116:11 | test.cpp:116:7:116:11 | | test.cpp:130:10:130:10 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:140:10:140:10 | Store: i | file://:0:0:0:0 | 0 | 1 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:140:10:140:10 | Store: i | test.cpp:135:16:135:16 | InitializeParameter: x | 0 | false | CompareLT: ... < ... | test.cpp:139:11:139:15 | test.cpp:139:11:139:15 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp index d31de1d2b80..87653c2fa43 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp +++ b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp @@ -104,7 +104,7 @@ void test9(int x) { } // Phi nodes as bounds -int test10(int y, int z, bool use_y) { +void test10(int y, int z, bool use_y) { int x; if(use_y) { x = y; @@ -112,9 +112,9 @@ int test10(int y, int z, bool use_y) { x = z; } sink(); - for(int i = 0; i < x; i++) { - return i; - } + int i = source(); + if (i < x) + sink(i); } // Irreducible CFGs From 1bde11706efd98d0b89a1d7e2d357f3d0d6e9be6 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Mon, 13 Apr 2020 18:37:47 -0400 Subject: [PATCH 409/459] C++: Connect `InitializeIndirection` to `UnmodeledDefinition` The IR generation for `InitializeIndirection` currently connects its load operand to the result of the corresponding `InitializeParameter` instruction. This isn't exactly wrong, but it doesn't fit the IR invariant of "All unmodeled uses consume `UnmodeledDefinition`". Our current code doesn't care, because we just throw away all of the existing def-use information, modeled or otherwise, when we build unaliased SSA. However, some upcoming SSA changes don't work correctly if this invariant is broken. I've added the trivial IR generation change, along with a new sanity query. --- .../implementation/aliased_ssa/IRSanity.qll | 20 ++++++ .../cpp/ir/implementation/raw/IRSanity.qll | 20 ++++++ .../raw/internal/TranslatedFunction.qll | 2 +- .../implementation/unaliased_ssa/IRSanity.qll | 20 ++++++ .../ir/ir/aliased_ssa_sanity.expected | 1 + .../ir/ir/aliased_ssa_sanity_unsound.expected | 1 + .../test/library-tests/ir/ir/raw_ir.expected | 68 +++++++++---------- .../library-tests/ir/ir/raw_sanity.expected | 1 + .../ir/ir/unaliased_ssa_sanity.expected | 1 + .../ir/unaliased_ssa_sanity_unsound.expected | 1 + .../ir/ssa/aliased_ssa_sanity.expected | 1 + .../ssa/aliased_ssa_sanity_unsound.expected | 1 + .../ir/ssa/unaliased_ssa_sanity.expected | 1 + .../ssa/unaliased_ssa_sanity_unsound.expected | 1 + .../csharp/ir/implementation/raw/IRSanity.qll | 20 ++++++ .../implementation/unaliased_ssa/IRSanity.qll | 20 ++++++ 16 files changed, 144 insertions(+), 35 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 1bfc1c8275f..04d366c6340 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -454,7 +454,7 @@ abstract class TranslatedParameter extends TranslatedElement { result = getInstruction(InitializerVariableAddressTag()) or operandTag instanceof LoadOperandTag and - result = getInstruction(InitializerStoreTag()) + result = getTranslatedFunction(getFunction()).getUnmodeledDefinitionInstruction() ) or tag = InitializerIndirectStoreTag() and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index d74ce2920b0..b782cd8d741 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -69,7 +69,7 @@ bad_asts.cpp: # 26| mu26_4(unknown) = UnmodeledDefinition : # 26| r26_5(glval) = VariableAddress[a] : # 26| mu26_6(Point &) = InitializeParameter[a] : &:r26_5 -# 26| r26_7(Point &) = Load : &:r26_5, ~mu26_6 +# 26| r26_7(Point &) = Load : &:r26_5, ~mu26_4 # 26| mu26_8(unknown) = InitializeIndirection[a] : &:r26_7 # 27| r27_1(glval) = VariableAddress[b] : # 27| r27_2(glval) = VariableAddress[a] : @@ -769,7 +769,7 @@ ir.cpp: # 153| mu153_4(unknown) = UnmodeledDefinition : # 153| r153_5(glval) = VariableAddress[p] : # 153| mu153_6(int *) = InitializeParameter[p] : &:r153_5 -# 153| r153_7(int *) = Load : &:r153_5, ~mu153_6 +# 153| r153_7(int *) = Load : &:r153_5, ~mu153_4 # 153| mu153_8(unknown) = InitializeIndirection[p] : &:r153_7 # 153| r153_9(glval) = VariableAddress[i] : # 153| mu153_10(int) = InitializeParameter[i] : &:r153_9 @@ -850,7 +850,7 @@ ir.cpp: # 171| mu171_4(unknown) = UnmodeledDefinition : # 171| r171_5(glval) = VariableAddress[p] : # 171| mu171_6(int *) = InitializeParameter[p] : &:r171_5 -# 171| r171_7(int *) = Load : &:r171_5, ~mu171_6 +# 171| r171_7(int *) = Load : &:r171_5, ~mu171_4 # 171| mu171_8(unknown) = InitializeIndirection[p] : &:r171_7 # 171| r171_9(glval) = VariableAddress[i] : # 171| mu171_10(int) = InitializeParameter[i] : &:r171_9 @@ -972,11 +972,11 @@ ir.cpp: # 193| mu193_4(unknown) = UnmodeledDefinition : # 193| r193_5(glval) = VariableAddress[p] : # 193| mu193_6(int *) = InitializeParameter[p] : &:r193_5 -# 193| r193_7(int *) = Load : &:r193_5, ~mu193_6 +# 193| r193_7(int *) = Load : &:r193_5, ~mu193_4 # 193| mu193_8(unknown) = InitializeIndirection[p] : &:r193_7 # 193| r193_9(glval) = VariableAddress[q] : # 193| mu193_10(int *) = InitializeParameter[q] : &:r193_9 -# 193| r193_11(int *) = Load : &:r193_9, ~mu193_10 +# 193| r193_11(int *) = Load : &:r193_9, ~mu193_4 # 193| mu193_12(unknown) = InitializeIndirection[q] : &:r193_11 # 194| r194_1(glval) = VariableAddress[b] : # 194| mu194_2(bool) = Uninitialized[b] : &:r194_1 @@ -1038,7 +1038,7 @@ ir.cpp: # 204| mu204_4(unknown) = UnmodeledDefinition : # 204| r204_5(glval) = VariableAddress[p] : # 204| mu204_6(int *) = InitializeParameter[p] : &:r204_5 -# 204| r204_7(int *) = Load : &:r204_5, ~mu204_6 +# 204| r204_7(int *) = Load : &:r204_5, ~mu204_4 # 204| mu204_8(unknown) = InitializeIndirection[p] : &:r204_7 # 205| r205_1(glval) = VariableAddress[q] : # 205| mu205_2(int *) = Uninitialized[q] : &:r205_1 @@ -1672,7 +1672,7 @@ ir.cpp: # 341| mu341_4(unknown) = UnmodeledDefinition : # 341| r341_5(glval) = VariableAddress[p] : # 341| mu341_6(int *) = InitializeParameter[p] : &:r341_5 -# 341| r341_7(int *) = Load : &:r341_5, ~mu341_6 +# 341| r341_7(int *) = Load : &:r341_5, ~mu341_4 # 341| mu341_8(unknown) = InitializeIndirection[p] : &:r341_7 # 342| r342_1(int) = Constant[1] : # 342| r342_2(glval) = VariableAddress[p] : @@ -2951,11 +2951,11 @@ ir.cpp: # 622| mu622_4(unknown) = UnmodeledDefinition : # 622| r622_5(glval) = VariableAddress[r] : # 622| mu622_6(String &) = InitializeParameter[r] : &:r622_5 -# 622| r622_7(String &) = Load : &:r622_5, ~mu622_6 +# 622| r622_7(String &) = Load : &:r622_5, ~mu622_4 # 622| mu622_8(unknown) = InitializeIndirection[r] : &:r622_7 # 622| r622_9(glval) = VariableAddress[p] : # 622| mu622_10(String *) = InitializeParameter[p] : &:r622_9 -# 622| r622_11(String *) = Load : &:r622_9, ~mu622_10 +# 622| r622_11(String *) = Load : &:r622_9, ~mu622_4 # 622| mu622_12(unknown) = InitializeIndirection[p] : &:r622_11 # 622| r622_13(glval) = VariableAddress[s] : # 622| mu622_14(String) = InitializeParameter[s] : &:r622_13 @@ -3191,7 +3191,7 @@ ir.cpp: # 675| mu675_4(unknown) = UnmodeledDefinition : # 675| r675_5(glval) = VariableAddress[r] : # 675| mu675_6(int &) = InitializeParameter[r] : &:r675_5 -# 675| r675_7(int &) = Load : &:r675_5, ~mu675_6 +# 675| r675_7(int &) = Load : &:r675_5, ~mu675_4 # 675| mu675_8(unknown) = InitializeIndirection[r] : &:r675_7 # 676| r676_1(glval) = VariableAddress[#return] : # 676| r676_2(glval) = VariableAddress[r] : @@ -3384,7 +3384,7 @@ ir.cpp: # 715| mu715_4(unknown) = UnmodeledDefinition : # 715| r715_5(glval) = VariableAddress[x] : # 715| mu715_6(void *) = InitializeParameter[x] : &:r715_5 -# 715| r715_7(void *) = Load : &:r715_5, ~mu715_6 +# 715| r715_7(void *) = Load : &:r715_5, ~mu715_4 # 715| mu715_8(unknown) = InitializeIndirection[x] : &:r715_7 # 715| r715_9(glval) = VariableAddress[y] : # 715| mu715_10(char) = InitializeParameter[y] : &:r715_9 @@ -3508,7 +3508,7 @@ ir.cpp: # 735| Block 10 # 735| r735_2(glval) = VariableAddress[s] : # 735| mu735_3(char *) = InitializeParameter[s] : &:r735_2 -# 735| r735_4(char *) = Load : &:r735_2, ~mu735_3 +# 735| r735_4(char *) = Load : &:r735_2, ~mu724_4 # 735| mu735_5(unknown) = InitializeIndirection[s] : &:r735_4 # 736| r736_1(glval) = VariableAddress[#throw736:5] : # 736| mu736_2(String) = Uninitialized[#throw736:5] : &:r736_1 @@ -3531,7 +3531,7 @@ ir.cpp: # 738| Block 12 # 738| r738_2(glval) = VariableAddress[e] : # 738| mu738_3(String &) = InitializeParameter[e] : &:r738_2 -# 738| r738_4(String &) = Load : &:r738_2, ~mu738_3 +# 738| r738_4(String &) = Load : &:r738_2, ~mu724_4 # 738| mu738_5(unknown) = InitializeIndirection[e] : &:r738_4 # 738| v738_6(void) = NoOp : #-----| Goto -> Block 14 @@ -3555,7 +3555,7 @@ ir.cpp: # 745| r745_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Base &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Base &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Base &) = Load : &:r0_1, ~mu745_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 #-----| r0_5(Base *) = CopyValue : r745_5 #-----| r0_6(glval) = FieldAddress[base_s] : r0_5 @@ -3594,7 +3594,7 @@ ir.cpp: # 745| r745_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Base &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Base &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Base &) = Load : &:r0_1, ~mu745_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 # 745| r745_6(glval) = FieldAddress[base_s] : r745_5 # 745| r745_7(glval) = FunctionAddress[String] : @@ -3652,7 +3652,7 @@ ir.cpp: # 754| r754_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Middle &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Middle &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Middle &) = Load : &:r0_1, ~mu754_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 #-----| r0_5(Middle *) = CopyValue : r754_5 #-----| r0_6(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_5 @@ -3752,7 +3752,7 @@ ir.cpp: # 763| r763_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Derived &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Derived &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Derived &) = Load : &:r0_1, ~mu763_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 #-----| r0_5(Derived *) = CopyValue : r763_5 #-----| r0_6(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_5 @@ -4483,7 +4483,7 @@ ir.cpp: # 883| mu883_6(..(*)(..)) = InitializeParameter[pfn] : &:r883_5 # 883| r883_7(glval) = VariableAddress[p] : # 883| mu883_8(void *) = InitializeParameter[p] : &:r883_7 -# 883| r883_9(void *) = Load : &:r883_7, ~mu883_8 +# 883| r883_9(void *) = Load : &:r883_7, ~mu883_4 # 883| mu883_10(unknown) = InitializeIndirection[p] : &:r883_9 # 884| r884_1(glval<..(*)(..)>) = VariableAddress[pfn] : # 884| r884_2(..(*)(..)) = Load : &:r884_1, ~mu883_4 @@ -4512,7 +4512,7 @@ ir.cpp: # 888| mu888_6(int) = InitializeParameter[x] : &:r888_5 # 888| r888_7(glval<__va_list_tag *>) = VariableAddress[args] : # 888| mu888_8(__va_list_tag *) = InitializeParameter[args] : &:r888_7 -# 888| r888_9(__va_list_tag *) = Load : &:r888_7, ~mu888_8 +# 888| r888_9(__va_list_tag *) = Load : &:r888_7, ~mu888_4 # 888| mu888_10(unknown) = InitializeIndirection[args] : &:r888_9 # 889| r889_1(glval<__va_list_tag[1]>) = VariableAddress[args2] : # 889| mu889_2(__va_list_tag[1]) = Uninitialized[args2] : &:r889_1 @@ -4561,7 +4561,7 @@ ir.cpp: # 896| mu896_6(int) = InitializeParameter[x] : &:r896_5 # 896| r896_7(glval) = VariableAddress[#ellipsis] : # 896| mu896_8(unknown[11]) = InitializeParameter[#ellipsis] : &:r896_7 -# 896| r896_9(unknown[11]) = Load : &:r896_7, ~mu896_8 +# 896| r896_9(unknown[11]) = Load : &:r896_7, ~mu896_4 # 896| mu896_10(unknown) = InitializeIndirection[#ellipsis] : &:r896_9 # 897| r897_1(glval<__va_list_tag[1]>) = VariableAddress[args] : # 897| mu897_2(__va_list_tag[1]) = Uninitialized[args] : &:r897_1 @@ -5048,7 +5048,7 @@ ir.cpp: # 996| mu996_4(unknown) = UnmodeledDefinition : # 996| r996_5(glval) = VariableAddress[a] : # 996| mu996_6(int *) = InitializeParameter[a] : &:r996_5 -# 996| r996_7(int *) = Load : &:r996_5, ~mu996_6 +# 996| r996_7(int *) = Load : &:r996_5, ~mu996_4 # 996| mu996_8(unknown) = InitializeIndirection[a] : &:r996_7 # 996| r996_9(glval<..(*)(..)>) = VariableAddress[fn] : # 996| mu996_10(..(*)(..)) = InitializeParameter[fn] : &:r996_9 @@ -5222,7 +5222,7 @@ ir.cpp: # 1040| mu1040_6(int) = InitializeParameter[x] : &:r1040_5 # 1040| r1040_7(glval) = VariableAddress[s] : # 1040| mu1040_8(String &) = InitializeParameter[s] : &:r1040_7 -# 1040| r1040_9(String &) = Load : &:r1040_7, ~mu1040_8 +# 1040| r1040_9(String &) = Load : &:r1040_7, ~mu1040_4 # 1040| mu1040_10(unknown) = InitializeIndirection[s] : &:r1040_9 # 1041| r1041_1(glval) = VariableAddress[lambda_empty] : # 1041| r1041_2(glval) = VariableAddress[#temp1041:23] : @@ -5645,7 +5645,7 @@ ir.cpp: # 1077| mu1077_4(unknown) = UnmodeledDefinition : # 1077| r1077_5(glval &>) = VariableAddress[v] : # 1077| mu1077_6(vector &) = InitializeParameter[v] : &:r1077_5 -# 1077| r1077_7(vector &) = Load : &:r1077_5, ~mu1077_6 +# 1077| r1077_7(vector &) = Load : &:r1077_5, ~mu1077_4 # 1077| mu1077_8(unknown) = InitializeIndirection[v] : &:r1077_7 # 1078| r1078_1(glval &>) = VariableAddress[(__range)] : # 1078| r1078_2(glval &>) = VariableAddress[v] : @@ -5838,13 +5838,13 @@ ir.cpp: # 1113| mu1113_4(unknown) = UnmodeledDefinition : # 1113| r1113_5(glval) = VariableAddress[a] : # 1113| mu1113_6(unsigned int &) = InitializeParameter[a] : &:r1113_5 -# 1113| r1113_7(unsigned int &) = Load : &:r1113_5, ~mu1113_6 +# 1113| r1113_7(unsigned int &) = Load : &:r1113_5, ~mu1113_4 # 1113| mu1113_8(unknown) = InitializeIndirection[a] : &:r1113_7 # 1113| r1113_9(glval) = VariableAddress[b] : # 1113| mu1113_10(unsigned int) = InitializeParameter[b] : &:r1113_9 # 1113| r1113_11(glval) = VariableAddress[c] : # 1113| mu1113_12(unsigned int &) = InitializeParameter[c] : &:r1113_11 -# 1113| r1113_13(unsigned int &) = Load : &:r1113_11, ~mu1113_12 +# 1113| r1113_13(unsigned int &) = Load : &:r1113_11, ~mu1113_4 # 1113| mu1113_14(unknown) = InitializeIndirection[c] : &:r1113_13 # 1113| r1113_15(glval) = VariableAddress[d] : # 1113| mu1113_16(unsigned int) = InitializeParameter[d] : &:r1113_15 @@ -6008,7 +6008,7 @@ ir.cpp: # 1153| Block 10 # 1153| r1153_2(glval) = VariableAddress[s] : # 1153| mu1153_3(char *) = InitializeParameter[s] : &:r1153_2 -# 1153| r1153_4(char *) = Load : &:r1153_2, ~mu1153_3 +# 1153| r1153_4(char *) = Load : &:r1153_2, ~mu1142_4 # 1153| mu1153_5(unknown) = InitializeIndirection[s] : &:r1153_4 # 1154| r1154_1(glval) = VariableAddress[#throw1154:5] : # 1154| mu1154_2(String) = Uninitialized[#throw1154:5] : &:r1154_1 @@ -6031,7 +6031,7 @@ ir.cpp: # 1156| Block 12 # 1156| r1156_2(glval) = VariableAddress[e] : # 1156| mu1156_3(String &) = InitializeParameter[e] : &:r1156_2 -# 1156| r1156_4(String &) = Load : &:r1156_2, ~mu1156_3 +# 1156| r1156_4(String &) = Load : &:r1156_2, ~mu1142_4 # 1156| mu1156_5(unknown) = InitializeIndirection[e] : &:r1156_4 # 1156| v1156_6(void) = NoOp : #-----| Goto -> Block 13 @@ -6385,7 +6385,7 @@ ir.cpp: # 1240| mu1240_4(unknown) = UnmodeledDefinition : # 1240| r1240_5(glval) = VariableAddress[dynamic] : # 1240| mu1240_6(char *) = InitializeParameter[dynamic] : &:r1240_5 -# 1240| r1240_7(char *) = Load : &:r1240_5, ~mu1240_6 +# 1240| r1240_7(char *) = Load : &:r1240_5, ~mu1240_4 # 1240| mu1240_8(unknown) = InitializeIndirection[dynamic] : &:r1240_7 # 1241| r1241_1(glval) = VariableAddress[a#init] : # 1241| r1241_2(bool) = Load : &:r1241_1, ~mu1240_4 @@ -6461,11 +6461,11 @@ ir.cpp: # 1251| mu1251_4(unknown) = UnmodeledDefinition : # 1251| r1251_5(glval) = VariableAddress[s1] : # 1251| mu1251_6(char *) = InitializeParameter[s1] : &:r1251_5 -# 1251| r1251_7(char *) = Load : &:r1251_5, ~mu1251_6 +# 1251| r1251_7(char *) = Load : &:r1251_5, ~mu1251_4 # 1251| mu1251_8(unknown) = InitializeIndirection[s1] : &:r1251_7 # 1251| r1251_9(glval) = VariableAddress[s2] : # 1251| mu1251_10(char *) = InitializeParameter[s2] : &:r1251_9 -# 1251| r1251_11(char *) = Load : &:r1251_9, ~mu1251_10 +# 1251| r1251_11(char *) = Load : &:r1251_9, ~mu1251_4 # 1251| mu1251_12(unknown) = InitializeIndirection[s2] : &:r1251_11 # 1252| r1252_1(glval) = VariableAddress[buffer] : # 1252| mu1252_2(char[1024]) = Uninitialized[buffer] : &:r1252_1 @@ -6512,7 +6512,7 @@ ir.cpp: # 1261| mu1261_4(unknown) = UnmodeledDefinition : # 1261| r1261_5(glval) = VariableAddress[a] : # 1261| mu1261_6(A *) = InitializeParameter[a] : &:r1261_5 -# 1261| r1261_7(A *) = Load : &:r1261_5, ~mu1261_6 +# 1261| r1261_7(A *) = Load : &:r1261_5, ~mu1261_4 # 1261| mu1261_8(unknown) = InitializeIndirection[a] : &:r1261_7 # 1261| r1261_9(glval) = VariableAddress[x] : # 1261| mu1261_10(int) = InitializeParameter[x] : &:r1261_9 @@ -6539,7 +6539,7 @@ ir.cpp: # 1270| mu1270_6(int) = InitializeParameter[int_arg] : &:r1270_5 # 1270| r1270_7(glval) = VariableAddress[a_arg] : # 1270| mu1270_8(A *) = InitializeParameter[a_arg] : &:r1270_7 -# 1270| r1270_9(A *) = Load : &:r1270_7, ~mu1270_8 +# 1270| r1270_9(A *) = Load : &:r1270_7, ~mu1270_4 # 1270| mu1270_10(unknown) = InitializeIndirection[a_arg] : &:r1270_9 # 1271| r1271_1(glval) = VariableAddress[c] : # 1271| mu1271_2(C) = Uninitialized[c] : &:r1271_1 @@ -6686,7 +6686,7 @@ struct_init.cpp: # 16| mu16_4(unknown) = UnmodeledDefinition : # 16| r16_5(glval) = VariableAddress[info] : # 16| mu16_6(Info *) = InitializeParameter[info] : &:r16_5 -# 16| r16_7(Info *) = Load : &:r16_5, ~mu16_6 +# 16| r16_7(Info *) = Load : &:r16_5, ~mu16_4 # 16| mu16_8(unknown) = InitializeIndirection[info] : &:r16_7 # 17| r17_1(glval) = VariableAddress[info] : # 17| r17_2(Info *) = Load : &:r17_1, ~mu16_4 @@ -6766,7 +6766,7 @@ struct_init.cpp: # 36| mu36_4(unknown) = UnmodeledDefinition : # 36| r36_5(glval) = VariableAddress[name1] : # 36| mu36_6(char *) = InitializeParameter[name1] : &:r36_5 -# 36| r36_7(char *) = Load : &:r36_5, ~mu36_6 +# 36| r36_7(char *) = Load : &:r36_5, ~mu36_4 # 36| mu36_8(unknown) = InitializeIndirection[name1] : &:r36_7 # 37| r37_1(glval) = VariableAddress[static_infos#init] : # 37| r37_2(bool) = Load : &:r37_1, ~mu36_4 diff --git a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected index 1e78ae87f40..e2db1e65034 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected index 1e78ae87f40..e2db1e65034 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected index 1e78ae87f40..e2db1e65034 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected index 1e78ae87f40..e2db1e65034 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. From 10824f961280f538d9064773486a22ceec882fb4 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 13 Apr 2020 15:22:30 -0700 Subject: [PATCH 410/459] C++: add method qldoc in Class.qll --- cpp/ql/src/semmle/code/cpp/Class.qll | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 67a2d11ff24..5aa9f43f48b 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -458,6 +458,15 @@ class Class extends UserType { exists(ClassDerivation d | d.getDerivedClass() = this and d = result) } + /** + * Gets class derivation number `index` of this class/struct, for example the + * `public B` is derivation 1 in the following code: + * ``` + * class D : public A, public B, public C { + * ... + * }; + * ``` + */ ClassDerivation getDerivation(int index) { exists(ClassDerivation d | d.getDerivedClass() = this and d.getIndex() = index and d = result) } @@ -900,6 +909,22 @@ class AbstractClass extends Class { class TemplateClass extends Class { TemplateClass() { usertypes(underlyingElement(this), _, 6) } + /** + * Gets a class instantiated from this template. + * + * For example for `MyTemplateClass` in the following code, the results are + * `MyTemplateClass` and `MyTemplateClass`: + * ``` + * template + * class MyTemplateClass { + * ... + * }; + * + * MyTemplateClass instance; + * + * MyTemplateClass instance; + * ``` + */ Class getAnInstantiation() { result.isConstructedFrom(this) and exists(result.getATemplateArgument()) From a9b88b6eaa8ff4aca7b43b5c9d59e4e8eae0dadf Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 6 Apr 2020 20:49:19 +0200 Subject: [PATCH 411/459] C#: Update data flow tests --- .../csharp/dataflow/LibraryTypeDataFlow.qll | 5 + .../dataflow/global/DataFlow.expected | 18 +- .../dataflow/global/DataFlowEdges.expected | 3816 ----------- .../dataflow/global/DataFlowEdges.ql | 17 - .../dataflow/global/DataFlowPath.expected | 182 +- .../dataflow/global/GetAnOutNode.expected | 135 +- .../dataflow/global/GlobalDataFlow.cs | 56 +- .../dataflow/global/TaintTracking.expected | 32 +- .../global/TaintTrackingEdges.expected | 5782 ----------------- .../dataflow/global/TaintTrackingEdges.ql | 17 - .../global/TaintTrackingPath.expected | 346 +- .../library/LibraryTypeDataFlow.expected | 2 + .../dataflow/local/DataFlow.expected | 20 +- .../dataflow/local/DataFlowStep.expected | 950 ++- .../dataflow/local/LocalDataFlow.cs | 119 +- .../dataflow/local/TaintTracking.expected | 111 +- .../dataflow/local/TaintTrackingStep.expected | 1204 ++-- 17 files changed, 1342 insertions(+), 11470 deletions(-) delete mode 100644 csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.expected delete mode 100644 csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.ql delete mode 100644 csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.expected delete mode 100644 csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.ql diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index 87eee2a80be..26b6e5f7b96 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -755,6 +755,11 @@ class IEnumerableFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() ) or + name = "AsQueryable" and + arity = 1 and + source = TCallableFlowSourceArg(0) and + sink = TCallableFlowSinkReturn() + or name = "Average" and ( arity = 2 and diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected index 38c978be390..ca81fb55904 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected @@ -28,15 +28,15 @@ | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.expected deleted file mode 100644 index b386a148705..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.expected +++ /dev/null @@ -1,3816 +0,0 @@ -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg : String[] | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 : String | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 : String | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) : String | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) : String | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) : String | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 : String | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) : String | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) : String | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) : String | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 : String | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) : String | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) : String | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) : String | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg : String[] | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 : String | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) : String | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) : String | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) : String | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 : String | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 : String | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) : String | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg : String[] | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted : String | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted : String | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) : String | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this : DataFlow | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this : DataFlow | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : T | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x : String[] | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... : String[] | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y : String[] | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s : String[] | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : T | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x : String[] | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y : String[] | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x : String[] | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call : T | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this : DataFlow | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 : String | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this : DataFlow | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 : String | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this : DataFlow | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted : T | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this : DataFlow | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this : DataFlow | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this : DataFlow | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call : String | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this : DataFlow | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this : DataFlow | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : String | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : String | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : String | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : String | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : String | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : Object | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : String | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x : String | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return : T | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this : This | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this : This | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access : This | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this : Sub | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.ql b/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.ql deleted file mode 100644 index d6d43ededd0..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.ql +++ /dev/null @@ -1,17 +0,0 @@ -import csharp -import DataFlow -import semmle.code.csharp.dataflow.internal.DataFlowPrivate - -class ConfigAny extends Configuration { - ConfigAny() { this = "ConfigAny" } - - override predicate isSource(Node source) { - source instanceof PostUpdateNode implies source.asExpr() instanceof ObjectCreation - } - - override predicate isSink(Node sink) { - sink instanceof PostUpdateNode implies sink.asExpr() instanceof ObjectCreation - } -} - -query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index cc1d49f3557..af0e92f2377 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -75,7 +75,7 @@ edges | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | +| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | @@ -84,7 +84,7 @@ edges | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | +| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | @@ -100,31 +100,31 @@ edges | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | +| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | +| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | +| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:406:9:406:11 | value : String | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | @@ -151,36 +151,36 @@ edges | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | @@ -304,42 +304,42 @@ nodes | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | semmle.label | access to property OutProperty : String | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | semmle.label | access to local variable sink19 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | semmle.label | tainted : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | semmle.label | value : String | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | semmle.label | tainted : String | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | semmle.label | value : String | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | semmle.label | "taint source" : String | | Splitting.cs:3:28:3:34 | tainted : String | semmle.label | tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | semmle.label | [b (line 3): false] call to method Return : String | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | semmle.label | [b (line 3): true] call to method Return : String | @@ -368,12 +368,12 @@ nodes | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | access to field SinkField0 | | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | access to local variable sink0 | | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | access to local variable sink1 | -| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | access to local variable sink11 | -| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | +| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | access to local variable sink11 | +| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | access to local variable sink2 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | access to local variable sink20 | -| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | access to local variable sink20 | +| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | | Capture.cs:12:19:12:24 | access to local variable sink27 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | access to local variable sink27 | | Capture.cs:21:23:21:28 | access to local variable sink28 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | access to local variable sink28 | | Capture.cs:30:19:30:24 | access to local variable sink29 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | access to local variable sink29 | @@ -390,20 +390,20 @@ nodes | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | access to local variable sink4 | | Capture.cs:122:15:122:20 | access to local variable sink40 | Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:122:15:122:20 | access to local variable sink40 | access to local variable sink40 | | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | access to local variable sink5 | -| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | -| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | -| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | +| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | +| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | +| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | access to local variable sink9 | | Splitting.cs:11:19:11:19 | access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:11:19:11:19 | access to local variable x | access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | access to local variable x | | Capture.cs:57:27:57:32 | access to parameter sink39 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:57:27:57:32 | access to parameter sink39 | access to parameter sink39 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | | Splitting.cs:21:28:21:32 | access to parameter value | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:21:28:21:32 | access to parameter value | access to parameter value | | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | access to property SinkProperty0 | diff --git a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected index 586a0ef9ca8..2b712d5c2f8 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected +++ b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected @@ -54,25 +54,25 @@ | GlobalDataFlow.cs:78:9:78:46 | call to method ReturnRef | ref | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | return | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | yield return | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select | return | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select | yield return | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:59:82:72 | call to method First | return | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip | return | GlobalDataFlow.cs:84:22:84:136 | call to method Zip | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip | yield return | GlobalDataFlow.cs:84:22:84:136 | call to method Zip | -| GlobalDataFlow.cs:84:59:84:72 | call to method First | return | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:84:125:84:135 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip | return | GlobalDataFlow.cs:86:22:86:136 | call to method Zip | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip | yield return | GlobalDataFlow.cs:86:22:86:136 | call to method Zip | -| GlobalDataFlow.cs:86:106:86:119 | call to method First | return | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:86:125:86:135 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate | return | GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate | -| GlobalDataFlow.cs:88:43:88:61 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:64:88:69 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate | return | GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate | -| GlobalDataFlow.cs:90:75:90:88 | call to method First | return | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:90:91:90:109 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:112:90:117 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | +| GlobalDataFlow.cs:80:22:80:93 | call to method First | return | GlobalDataFlow.cs:80:22:80:93 | call to method First | +| GlobalDataFlow.cs:82:22:82:87 | call to method Select | return | GlobalDataFlow.cs:82:22:82:87 | call to method Select | +| GlobalDataFlow.cs:82:22:82:87 | call to method Select | yield return | GlobalDataFlow.cs:82:22:82:87 | call to method Select | +| GlobalDataFlow.cs:82:22:82:95 | call to method First | return | GlobalDataFlow.cs:82:22:82:95 | call to method First | +| GlobalDataFlow.cs:82:76:82:86 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func | +| GlobalDataFlow.cs:84:22:84:128 | call to method Zip | return | GlobalDataFlow.cs:84:22:84:128 | call to method Zip | +| GlobalDataFlow.cs:84:22:84:128 | call to method Zip | yield return | GlobalDataFlow.cs:84:22:84:128 | call to method Zip | +| GlobalDataFlow.cs:84:22:84:136 | call to method First | return | GlobalDataFlow.cs:84:22:84:136 | call to method First | +| GlobalDataFlow.cs:84:117:84:127 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... | +| GlobalDataFlow.cs:86:22:86:128 | call to method Zip | return | GlobalDataFlow.cs:86:22:86:128 | call to method Zip | +| GlobalDataFlow.cs:86:22:86:128 | call to method Zip | yield return | GlobalDataFlow.cs:86:22:86:128 | call to method Zip | +| GlobalDataFlow.cs:86:22:86:136 | call to method First | return | GlobalDataFlow.cs:86:22:86:136 | call to method First | +| GlobalDataFlow.cs:86:117:86:127 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... | +| GlobalDataFlow.cs:88:22:88:110 | call to method Aggregate | return | GlobalDataFlow.cs:88:22:88:110 | call to method Aggregate | +| GlobalDataFlow.cs:88:83:88:101 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... | +| GlobalDataFlow.cs:88:104:88:109 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... | +| GlobalDataFlow.cs:90:22:90:110 | call to method Aggregate | return | GlobalDataFlow.cs:90:22:90:110 | call to method Aggregate | +| GlobalDataFlow.cs:90:83:90:101 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... | +| GlobalDataFlow.cs:90:104:90:109 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... | | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | out | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | ref | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | return | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | @@ -89,28 +89,30 @@ | GlobalDataFlow.cs:108:9:108:49 | call to method ReturnRef | ref | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | | GlobalDataFlow.cs:110:9:110:49 | call to method ReturnRef | out | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | | GlobalDataFlow.cs:110:9:110:49 | call to method ReturnRef | ref | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | return | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | yield return | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | +| GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | return | GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | +| GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | yield return | GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | +| GlobalDataFlow.cs:112:20:112:94 | call to method First | return | GlobalDataFlow.cs:112:20:112:94 | call to method First | | GlobalDataFlow.cs:114:20:114:82 | call to method Select | return | GlobalDataFlow.cs:114:20:114:82 | call to method Select | | GlobalDataFlow.cs:114:20:114:82 | call to method Select | yield return | GlobalDataFlow.cs:114:20:114:82 | call to method Select | +| GlobalDataFlow.cs:114:20:114:90 | call to method First | return | GlobalDataFlow.cs:114:20:114:90 | call to method First | | GlobalDataFlow.cs:114:76:114:81 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip | return | GlobalDataFlow.cs:116:20:116:134 | call to method Zip | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip | yield return | GlobalDataFlow.cs:116:20:116:134 | call to method Zip | -| GlobalDataFlow.cs:116:57:116:70 | call to method First | return | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:116:123:116:133 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip | return | GlobalDataFlow.cs:118:20:118:134 | call to method Zip | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip | yield return | GlobalDataFlow.cs:118:20:118:134 | call to method Zip | -| GlobalDataFlow.cs:118:104:118:117 | call to method First | return | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:118:123:118:133 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate | return | GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate | -| GlobalDataFlow.cs:120:41:120:55 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:58:120:63 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate | return | GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate | -| GlobalDataFlow.cs:122:41:122:59 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:62:122:68 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate | return | GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate | -| GlobalDataFlow.cs:124:46:124:58 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:61:124:66 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | +| GlobalDataFlow.cs:116:20:116:126 | call to method Zip | return | GlobalDataFlow.cs:116:20:116:126 | call to method Zip | +| GlobalDataFlow.cs:116:20:116:126 | call to method Zip | yield return | GlobalDataFlow.cs:116:20:116:126 | call to method Zip | +| GlobalDataFlow.cs:116:20:116:134 | call to method First | return | GlobalDataFlow.cs:116:20:116:134 | call to method First | +| GlobalDataFlow.cs:116:115:116:125 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:116:115:116:125 | [output] (...) => ... | +| GlobalDataFlow.cs:118:20:118:126 | call to method Zip | return | GlobalDataFlow.cs:118:20:118:126 | call to method Zip | +| GlobalDataFlow.cs:118:20:118:126 | call to method Zip | yield return | GlobalDataFlow.cs:118:20:118:126 | call to method Zip | +| GlobalDataFlow.cs:118:20:118:134 | call to method First | return | GlobalDataFlow.cs:118:20:118:134 | call to method First | +| GlobalDataFlow.cs:118:115:118:125 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:118:115:118:125 | [output] (...) => ... | +| GlobalDataFlow.cs:120:20:120:104 | call to method Aggregate | return | GlobalDataFlow.cs:120:20:120:104 | call to method Aggregate | +| GlobalDataFlow.cs:120:81:120:95 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:81:120:95 | [output] (...) => ... | +| GlobalDataFlow.cs:120:98:120:103 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:98:120:103 | [output] (...) => ... | +| GlobalDataFlow.cs:122:20:122:109 | call to method Aggregate | return | GlobalDataFlow.cs:122:20:122:109 | call to method Aggregate | +| GlobalDataFlow.cs:122:81:122:99 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:81:122:99 | [output] (...) => ... | +| GlobalDataFlow.cs:122:102:122:108 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:102:122:108 | [output] (...) => ... | +| GlobalDataFlow.cs:124:20:124:107 | call to method Aggregate | return | GlobalDataFlow.cs:124:20:124:107 | call to method Aggregate | +| GlobalDataFlow.cs:124:86:124:98 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:86:124:98 | [output] (...) => ... | +| GlobalDataFlow.cs:124:101:124:106 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:101:124:106 | [output] (...) => ... | | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | out | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | ref | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | return | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | @@ -130,6 +132,7 @@ | GlobalDataFlow.cs:159:9:159:25 | call to method OutRef | ref | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | return | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | yield return | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | +| GlobalDataFlow.cs:161:22:161:39 | call to method First | return | GlobalDataFlow.cs:161:22:161:39 | call to method First | | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | return | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | return | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | | GlobalDataFlow.cs:169:9:169:31 | call to method NonOutOut | out | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) | @@ -150,32 +153,42 @@ | GlobalDataFlow.cs:193:37:193:42 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | return | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | return | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | return | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select | return | GlobalDataFlow.cs:210:22:210:39 | call to method Select | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select | yield return | GlobalDataFlow.cs:210:22:210:39 | call to method Select | -| GlobalDataFlow.cs:210:37:210:38 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | +| GlobalDataFlow.cs:207:38:207:75 | call to method AsQueryable | return | GlobalDataFlow.cs:207:38:207:75 | call to method AsQueryable | +| GlobalDataFlow.cs:208:41:208:77 | call to method AsQueryable | return | GlobalDataFlow.cs:208:41:208:77 | call to method AsQueryable | +| GlobalDataFlow.cs:211:76:211:90 | call to method ReturnCheck2 | return | GlobalDataFlow.cs:211:76:211:90 | call to method ReturnCheck2 | | GlobalDataFlow.cs:212:22:212:39 | call to method Select | return | GlobalDataFlow.cs:212:22:212:39 | call to method Select | -| GlobalDataFlow.cs:212:37:212:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select | return | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select | yield return | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:37:214:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | return | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select | return | GlobalDataFlow.cs:220:23:220:43 | call to method Select | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select | yield return | GlobalDataFlow.cs:220:23:220:43 | call to method Select | -| GlobalDataFlow.cs:220:41:220:42 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select | return | GlobalDataFlow.cs:222:19:222:39 | call to method Select | -| GlobalDataFlow.cs:222:37:222:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | +| GlobalDataFlow.cs:212:22:212:39 | call to method Select | yield return | GlobalDataFlow.cs:212:22:212:39 | call to method Select | +| GlobalDataFlow.cs:212:22:212:47 | call to method First | return | GlobalDataFlow.cs:212:22:212:47 | call to method First | +| GlobalDataFlow.cs:212:37:212:38 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 | +| GlobalDataFlow.cs:214:22:214:39 | call to method Select | return | GlobalDataFlow.cs:214:22:214:39 | call to method Select | +| GlobalDataFlow.cs:214:22:214:47 | call to method First | return | GlobalDataFlow.cs:214:22:214:47 | call to method First | +| GlobalDataFlow.cs:214:37:214:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 | +| GlobalDataFlow.cs:216:22:216:49 | call to method Select | return | GlobalDataFlow.cs:216:22:216:49 | call to method Select | +| GlobalDataFlow.cs:216:22:216:49 | call to method Select | yield return | GlobalDataFlow.cs:216:22:216:49 | call to method Select | +| GlobalDataFlow.cs:216:22:216:57 | call to method First | return | GlobalDataFlow.cs:216:22:216:57 | call to method First | +| GlobalDataFlow.cs:216:37:216:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func | +| GlobalDataFlow.cs:221:76:221:92 | call to method NonReturnCheck | return | GlobalDataFlow.cs:221:76:221:92 | call to method NonReturnCheck | +| GlobalDataFlow.cs:222:23:222:43 | call to method Select | return | GlobalDataFlow.cs:222:23:222:43 | call to method Select | +| GlobalDataFlow.cs:222:23:222:43 | call to method Select | yield return | GlobalDataFlow.cs:222:23:222:43 | call to method Select | +| GlobalDataFlow.cs:222:23:222:51 | call to method First | return | GlobalDataFlow.cs:222:23:222:51 | call to method First | +| GlobalDataFlow.cs:222:41:222:42 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:222:41:222:42 | [output] access to local variable f1 | | GlobalDataFlow.cs:224:19:224:39 | call to method Select | return | GlobalDataFlow.cs:224:19:224:39 | call to method Select | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select | yield return | GlobalDataFlow.cs:224:19:224:39 | call to method Select | -| GlobalDataFlow.cs:224:37:224:38 | [implicit call] access to local variable f3 | return | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | +| GlobalDataFlow.cs:224:19:224:47 | call to method First | return | GlobalDataFlow.cs:224:19:224:47 | call to method First | +| GlobalDataFlow.cs:224:37:224:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f2 | | GlobalDataFlow.cs:226:19:226:39 | call to method Select | return | GlobalDataFlow.cs:226:19:226:39 | call to method Select | -| GlobalDataFlow.cs:226:37:226:38 | [implicit call] access to local variable f4 | return | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select | return | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select | yield return | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:37:228:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | return | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call | return | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call | return | GlobalDataFlow.cs:431:44:431:47 | delegate call | +| GlobalDataFlow.cs:226:19:226:39 | call to method Select | yield return | GlobalDataFlow.cs:226:19:226:39 | call to method Select | +| GlobalDataFlow.cs:226:19:226:47 | call to method First | return | GlobalDataFlow.cs:226:19:226:47 | call to method First | +| GlobalDataFlow.cs:226:37:226:38 | [implicit call] access to local variable f3 | return | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f3 | +| GlobalDataFlow.cs:228:19:228:39 | call to method Select | return | GlobalDataFlow.cs:228:19:228:39 | call to method Select | +| GlobalDataFlow.cs:228:19:228:47 | call to method First | return | GlobalDataFlow.cs:228:19:228:47 | call to method First | +| GlobalDataFlow.cs:228:37:228:38 | [implicit call] access to local variable f4 | return | GlobalDataFlow.cs:228:37:228:38 | [output] access to local variable f4 | +| GlobalDataFlow.cs:230:19:230:49 | call to method Select | return | GlobalDataFlow.cs:230:19:230:49 | call to method Select | +| GlobalDataFlow.cs:230:19:230:49 | call to method Select | yield return | GlobalDataFlow.cs:230:19:230:49 | call to method Select | +| GlobalDataFlow.cs:230:19:230:57 | call to method First | return | GlobalDataFlow.cs:230:19:230:57 | call to method First | +| GlobalDataFlow.cs:230:37:230:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:230:37:230:48 | [output] delegate creation of type Func | +| GlobalDataFlow.cs:279:17:279:38 | call to method ApplyFunc | return | GlobalDataFlow.cs:279:17:279:38 | call to method ApplyFunc | +| GlobalDataFlow.cs:368:16:368:19 | delegate call | return | GlobalDataFlow.cs:368:16:368:19 | delegate call | +| GlobalDataFlow.cs:433:44:433:47 | delegate call | return | GlobalDataFlow.cs:433:44:433:47 | delegate call | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | return | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | return | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | | Splitting.cs:20:22:20:30 | call to method Return | return | Splitting.cs:20:22:20:30 | call to method Return | diff --git a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs index 41630b7fd8f..83003aaea66 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs @@ -77,17 +77,17 @@ public class DataFlow var sink3 = ""; ReturnRef(sink2, ref sink3, ref sink3); Check(sink3); - var sink13 = ((IEnumerable)new string[] { sink3 }).SelectEven(x => x); + var sink13 = ((IEnumerable)new string[] { sink3 }).SelectEven(x => x).First(); Check(sink13); - var sink14 = ((IEnumerable)new string[] { sink13.First() }).Select(ReturnCheck); + var sink14 = ((IEnumerable)new string[] { sink13 }).Select(ReturnCheck).First(); Check(sink14); - var sink15 = ((IEnumerable)new string[] { sink14.First() }).Zip(((IEnumerable)new string[] { "" }), (x, y) => x); + var sink15 = ((IEnumerable)new string[] { sink14 }).Zip(((IEnumerable)new string[] { "" }), (x, y) => x).First(); Check(sink15); - var sink16 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15.First() }), (x, y) => y); + var sink16 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15 }), (x, y) => y).First(); Check(sink16); - var sink17 = sink14.Aggregate("", (acc, s) => acc + s, x => x); + var sink17 = ((IEnumerable)new string[] { sink14 }).Aggregate("", (acc, s) => acc + s, x => x); Check(sink17); - var sink18 = ((IEnumerable)new string[] { "" }).Aggregate(sink14.First(), (acc, s) => acc + s, x => x); + var sink18 = ((IEnumerable)new string[] { "" }).Aggregate(sink14, (acc, s) => acc + s, x => x); Check(sink18); int sink21; Int32.TryParse(sink18, out sink21); @@ -109,19 +109,19 @@ public class DataFlow Check(nonSink0); ReturnRef(sink1, ref sink1, ref nonSink0); Check(nonSink0); - var nonSink1 = ((IEnumerable)new string[] { nonSink0 }).SelectEven(x => x); - Check(nonSink1); - nonSink1 = ((IEnumerable)new string[] { nonSink0 }).Select(x => x); - Check(nonSink1); - nonSink1 = ((IEnumerable)new string[] { sink14.First() }).Zip(((IEnumerable)new string[] { "" }), (x, y) => y); - Check(nonSink1); - nonSink1 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15.First() }), (x, y) => x); - Check(nonSink1); - nonSink0 = sink14.Aggregate("", (acc, s) => acc, x => x); + nonSink0 = ((IEnumerable)new string[] { nonSink0 }).SelectEven(x => x).First(); Check(nonSink0); - nonSink0 = sink14.Aggregate("", (acc, s) => acc + s, x => ""); + nonSink0 = ((IEnumerable)new string[] { nonSink0 }).Select(x => x).First(); Check(nonSink0); - nonSink0 = nonSink1.Aggregate(sink1, (acc, s) => s, x => x); + nonSink0 = ((IEnumerable)new string[] { sink14 }).Zip(((IEnumerable)new string[] { "" }), (x, y) => y).First(); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15 }), (x, y) => x).First(); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { sink14 }).Aggregate("", (acc, s) => acc, x => x); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { sink14 }).Aggregate("", (acc, s) => acc + s, x => ""); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { nonSink0 }).Aggregate(sink1, (acc, s) => s, x => x); Check(nonSink0); int nonSink2; Int32.TryParse(nonSink0, out nonSink2); @@ -158,7 +158,7 @@ public class DataFlow var sink8 = ""; OutRef(ref sink8); Check(sink8); - var sink12 = OutYield(); + var sink12 = OutYield().First(); Check(sink12); var sink23 = TaintedParam(nonSink0); // even though the argument is not tainted, the parameter is considered tainted Check(sink23); @@ -202,30 +202,32 @@ public class DataFlow Check(nonSink0); } - public void M2(IQueryable tainted, IQueryable notTainted) + public void M2() { + IQueryable tainted = new[] { "taint source" }.AsQueryable(); + IQueryable notTainted = new[] { "not tainted" }.AsQueryable(); // Flow into a callable via library call, tainted Func f1 = sinkParam10 => { Check(sinkParam10); return sinkParam10; }; System.Linq.Expressions.Expression> f2 = x => ReturnCheck2(x); - var sink24 = tainted.Select(f1); + var sink24 = tainted.Select(f1).First(); Check(sink24); - var sink25 = tainted.Select(f2); + var sink25 = tainted.Select(f2).First(); Check(sink25); - var sink26 = tainted.Select(ReturnCheck3); + var sink26 = tainted.Select(ReturnCheck3).First(); Check(sink26); // Flow into a callable via library call, not tainted Func f3 = nonSinkParam => { Check(nonSinkParam); return nonSinkParam; }; System.Linq.Expressions.Expression> f4 = x => NonReturnCheck(x); - var nonSink = notTainted.Select(f1); + var nonSink = notTainted.Select(f1).First(); Check(nonSink); - nonSink = notTainted.Select(f2); + nonSink = notTainted.Select(f2).First(); Check(nonSink); - nonSink = notTainted.Select(f3); + nonSink = notTainted.Select(f3).First(); Check(nonSink); - nonSink = notTainted.Select(f4); + nonSink = notTainted.Select(f4).First(); Check(nonSink); - nonSink = notTainted.Select(ReturnCheck3); + nonSink = notTainted.Select(ReturnCheck3).First(); Check(nonSink); } diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected index 10d873cc2fc..57fd2c9e0c3 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected @@ -37,22 +37,22 @@ | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | +| GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | +| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | +| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | +| GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.expected deleted file mode 100644 index bd9d777b9dd..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.expected +++ /dev/null @@ -1,5782 +0,0 @@ -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:7:20:7:26 | tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:7:20:7:26 | tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:14:9:14:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:14:9:14:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:25:9:25:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:25:9:25:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:33:9:33:40 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:33:9:33:40 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:61:36:61:42 | access to parameter tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:61:36:61:42 | access to parameter tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:27:43:27:45 | arg | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:27:43:27:45 | arg : String | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:27:43:27:45 | arg | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:27:43:27:45 | arg : String | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg : String[] | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | -| Capture.cs:33:9:33:40 | call to method Select : IEnumerable | Capture.cs:33:9:33:50 | call to method ToArray | -| Capture.cs:33:9:33:40 | call to method Select : IEnumerable | Capture.cs:33:9:33:50 | call to method ToArray : String[] | -| Capture.cs:33:17:33:19 | " " : String | Capture.cs:33:9:33:21 | array creation of type String[] | -| Capture.cs:33:17:33:19 | " " : String | Capture.cs:33:9:33:21 | array creation of type String[] : String[] | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:40 | call to method Select | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:40 | call to method Select : IEnumerable | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:50 | call to method ToArray | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:50 | call to method ToArray : String[] | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:50:33:50:40 | nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:50:33:50:40 | nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:50:50:50:55 | sink39 | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:50:50:50:55 | sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 : String | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 : String | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) : String | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) : String | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) : String | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 : String | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) : String | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) : String | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) : String | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 : String | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) : String | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:87:44:87:46 | arg | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:87:44:87:46 | arg : String | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:87:44:87:46 | arg | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:87:44:87:46 | arg : String | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) : String | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) : String | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg : String[] | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 : String | -| Capture.cs:92:9:92:41 | call to method Select : IEnumerable | Capture.cs:92:9:92:51 | call to method ToArray | -| Capture.cs:92:9:92:41 | call to method Select : IEnumerable | Capture.cs:92:9:92:51 | call to method ToArray : String[] | -| Capture.cs:92:17:92:19 | " " : String | Capture.cs:92:9:92:21 | array creation of type String[] | -| Capture.cs:92:17:92:19 | " " : String | Capture.cs:92:9:92:21 | array creation of type String[] : String[] | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:41 | call to method Select | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:41 | call to method Select : IEnumerable | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:51 | call to method ToArray | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:51 | call to method ToArray : String[] | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) : String | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) : String | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) : String | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 : String | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 : String | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:125:25:125:31 | tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:125:25:125:31 | tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:132:9:132:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:132:9:132:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:144:9:144:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:144:9:144:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:153:9:153:45 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:153:9:153:45 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:160:22:160:38 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:160:22:160:38 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:168:25:168:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:168:25:168:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) : String | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:148:48:148:50 | arg | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:148:48:148:50 | arg : String | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:148:48:148:50 | arg | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:148:48:148:50 | arg : String | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg : String[] | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:153:9:153:45 | call to method Select : IEnumerable | Capture.cs:153:9:153:55 | call to method ToArray | -| Capture.cs:153:9:153:45 | call to method Select : IEnumerable | Capture.cs:153:9:153:55 | call to method ToArray : String[] | -| Capture.cs:153:17:153:19 | " " : String | Capture.cs:153:9:153:21 | array creation of type String[] | -| Capture.cs:153:17:153:19 | " " : String | Capture.cs:153:9:153:21 | array creation of type String[] : String[] | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:45 | call to method Select | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:45 | call to method Select : IEnumerable | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:55 | call to method ToArray | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:55 | call to method ToArray : String[] | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:164:37:164:37 | p | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:164:37:164:37 | p : String | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted : String | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted : String | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:188:26:188:26 | s | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) : String | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:202:34:202:34 | a | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:204:9:204:9 | access to parameter a : Action | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this : DataFlow | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this : DataFlow | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:79:80:79 | x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : T | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x : String[] | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:82:84:121 | (...) ... | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:82:84:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:22:84:136 | call to method Zip | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:126:84:126 | x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:126:84:126 | x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... : String[] | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:23:86:62 | (...) ... | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:23:86:62 | (...) ... : String[] | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y : String[] | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:22:86:136 | call to method Zip | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:129:86:129 | y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:129:86:129 | y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:49:88:49 | s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s : String[] | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:23:90:62 | (...) ... | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:97:90:97 | s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:97:90:97 | s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:84:112:84 | x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : T | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x : String[] | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:76:114:76 | x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:76:114:76 | x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:20:114:82 | call to method Select | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y : String[] | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:80:116:119 | (...) ... | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:20:116:134 | call to method Zip | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:127:116:127 | y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:127:116:127 | y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x : String[] | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:21:118:60 | (...) ... | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:20:118:134 | call to method Zip | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:124:118:124 | x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:124:118:124 | x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:47:122:47 | s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:52:124:52 | s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call : T | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this : DataFlow | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 : String | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this : DataFlow | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 : String | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this : DataFlow | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted : T | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this : DataFlow | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this : DataFlow | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:20:173:40 | call to method First | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:20:173:40 | call to method First : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this : DataFlow | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call : String | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this : DataFlow | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this : DataFlow | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:205:39:205:45 | tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:205:67:205:76 | notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:71:209:71 | x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:22:210:39 | call to method Select | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:22:212:39 | call to method Select | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:22:212:39 | call to method Select | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:71:219:71 | x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:23:220:43 | call to method Select | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:19:222:39 | call to method Select | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:19:222:39 | call to method Select | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:19:224:39 | call to method Select | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:19:226:39 | call to method Select | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:19:226:39 | call to method Select | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : String | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : String | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : String | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : String | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : String | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : Object | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : String | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:50:287:50 | z : Object | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:287:50:287:50 | z : Object | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:333:22:333:23 | "" : String | GlobalDataFlow.cs:333:22:333:23 | "" | -| GlobalDataFlow.cs:333:22:333:23 | "" : String | GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:334:22:334:35 | "taint source" | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:335:22:335:23 | "" : String | GlobalDataFlow.cs:335:22:335:23 | "" | -| GlobalDataFlow.cs:335:22:335:23 | "" : String | GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:355:22:355:23 | "" : String | GlobalDataFlow.cs:355:22:355:23 | "" | -| GlobalDataFlow.cs:355:22:355:23 | "" : String | GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:356:22:356:23 | "" : String | GlobalDataFlow.cs:356:22:356:23 | "" | -| GlobalDataFlow.cs:356:22:356:23 | "" : String | GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:359:41:359:41 | x : T | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:378:39:378:45 | tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:385:42:385:51 | nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:9:404:11 | value | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:9:404:11 | value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:9:410:11 | value | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:9:410:11 | value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:431:17:431:23 | ... % ... : Int32 | GlobalDataFlow.cs:431:17:431:28 | ... == ... | -| GlobalDataFlow.cs:431:17:431:23 | ... % ... : Int32 | GlobalDataFlow.cs:431:17:431:28 | ... == ... : Boolean | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:3:18:3:18 | b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:3:18:3:18 | b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:5:13:5:13 | access to parameter b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:5:13:5:13 | access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:3:28:3:34 | tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:3:28:3:34 | tainted : String | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... : Boolean | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... : Boolean | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... : Boolean | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:26:16:26 | x : T | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:32:16:32 | access to parameter x : T | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x : String | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return : T | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:24:18:24:18 | b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:24:18:24:18 | b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:26:13:26:13 | access to parameter b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:26:13:26:13 | access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:24:28:24:34 | tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:24:28:24:34 | tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... : Boolean | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... : Boolean | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... : Boolean | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:27:9:31 | other : Object | This.cs:9:27:9:31 | other | -| This.cs:9:27:9:31 | other : Object | This.cs:9:27:9:31 | other : This | -| This.cs:9:27:9:31 | other : Object | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : Object | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : Object | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : Object | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : Object | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : Object | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this : This | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this : This | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access : This | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this : Sub | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.ql b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.ql deleted file mode 100644 index 163130bea8f..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.ql +++ /dev/null @@ -1,17 +0,0 @@ -import csharp -import DataFlow -import semmle.code.csharp.dataflow.internal.DataFlowPrivate - -class ConfigAny extends TaintTracking::Configuration { - ConfigAny() { this = "ConfigAny" } - - override predicate isSource(Node source) { - source instanceof PostUpdateNode implies source.asExpr() instanceof ObjectCreation - } - - override predicate isSink(Node sink) { - sink instanceof PostUpdateNode implies sink.asExpr() instanceof ObjectCreation - } -} - -query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index c612897d3ee..7495630f875 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -75,7 +75,7 @@ edges | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | +| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | @@ -84,7 +84,7 @@ edges | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | +| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | @@ -100,31 +100,31 @@ edges | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | +| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | +| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | +| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:406:9:406:11 | value : String | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | @@ -140,27 +140,27 @@ edges | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | +| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | +| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | +| GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | +| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | +| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | +| GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | +| GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | +| GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | +| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | @@ -175,56 +175,56 @@ edges | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | +| GlobalDataFlow.cs:211:71:211:71 | x : IQueryable | GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | +| GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | +| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable | +| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | +| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | +| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:211:71:211:71 | x : IQueryable | +| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | +| GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | +| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable | +| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | @@ -333,22 +333,22 @@ nodes | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | semmle.label | call to method SelectEven : IEnumerable | | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | semmle.label | (...) ... : String[] | | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | semmle.label | access to local variable sink13 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | semmle.label | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | semmle.label | access to local variable sink14 | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | semmle.label | (...) ... : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | semmle.label | access to local variable sink15 | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | semmle.label | (...) ... : String[] | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | semmle.label | access to local variable sink16 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | semmle.label | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | semmle.label | access to local variable sink17 | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | semmle.label | call to method First : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | semmle.label | access to local variable sink14 : String | +| GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | semmle.label | access to local variable sink18 | | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | semmle.label | access to local variable sink21 | | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | semmle.label | access to local variable sink22 | @@ -375,64 +375,64 @@ nodes | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | semmle.label | access to property OutProperty : String | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | semmle.label | access to local variable sink19 | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | semmle.label | tainted : IQueryable | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | semmle.label | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | semmle.label | access to parameter sinkParam10 | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | semmle.label | x : IQueryable | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | semmle.label | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | semmle.label | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | semmle.label | access to local variable sink24 | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | semmle.label | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | semmle.label | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | semmle.label | access to local variable sink25 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | semmle.label | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | semmle.label | sinkParam8 : String[] | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | semmle.label | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | semmle.label | "taint source" : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | semmle.label | tainted : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | semmle.label | value : String | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable | semmle.label | sinkParam10 : IQueryable | +| GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | semmle.label | access to parameter sinkParam10 | +| GlobalDataFlow.cs:211:71:211:71 | x : IQueryable | semmle.label | x : IQueryable | +| GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | semmle.label | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | semmle.label | [output] access to local variable f1 : String | +| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | semmle.label | access to local variable sink24 | +| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | semmle.label | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | semmle.label | [output] access to local variable f2 : String | +| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | semmle.label | access to local variable sink25 | +| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | semmle.label | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | +| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | semmle.label | sinkParam8 : String[] | +| GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | +| GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | +| GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | +| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable | semmle.label | sinkParam11 : IQueryable | +| GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable | semmle.label | "taint source" : IEnumerable | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | semmle.label | tainted : String | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | semmle.label | value : String | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | semmle.label | "taint source" : String | | Splitting.cs:3:28:3:34 | tainted : String | semmle.label | tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | semmle.label | [b (line 3): false] call to method Return : String | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | semmle.label | [b (line 3): true] call to method Return : String | @@ -485,30 +485,30 @@ nodes | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | access to local variable sink22 | | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | access to local variable sink4 | | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | access to local variable sink5 | -| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | -| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | -| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | -| GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | access to local variable sink12 | -| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | +| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | +| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | +| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | +| GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | access to local variable sink12 | +| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | access to local variable sink9 | -| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | -| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | access to local variable sink24 | -| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | access to local variable sink25 | -| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | access to local variable sink26 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | access to local variable sink11 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | access to local variable sink20 | +| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | +| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | +| GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | access to parameter sinkParam10 | +| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | access to local variable sink24 | +| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | access to local variable sink25 | +| GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | access to local variable sink26 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | access to local variable sink11 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:11:19:11:19 | access to local variable x | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected index 6631539ed2d..ce4eba806a2 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected @@ -1139,6 +1139,8 @@ | System.Linq.Queryable.Aggregate(IQueryable, Expression>) | output from argument 1 -> return | false | | System.Linq.Queryable.All(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Any(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.AsQueryable(IEnumerable) | argument 0 -> return | false | +| System.Linq.Queryable.AsQueryable(IEnumerable) | argument 0 -> return | false | | System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | diff --git a/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected b/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected index 78c0204ed20..e9a03e58b0a 100644 --- a/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected @@ -1,16 +1,12 @@ | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | | SSA.cs:9:15:9:22 | access to local variable ssaSink0 | | SSA.cs:25:15:25:22 | access to local variable ssaSink1 | | SSA.cs:43:15:43:22 | access to local variable ssaSink2 | diff --git a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 658dc392eee..e3166a0df30 100644 --- a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -24,8 +24,7 @@ | Capture.cs:58:21:58:21 | 1 | Capture.cs:58:17:58:21 | SSA def(i) | | Capture.cs:61:17:61:17 | 1 | Capture.cs:61:13:61:17 | SSA def(i) | | Capture.cs:63:9:63:17 | SSA call def(i) | Capture.cs:64:13:64:13 | access to local variable i | -| LocalDataFlow.cs:49:23:49:23 | this | LocalDataFlow.cs:299:39:299:51 | this access | -| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:96:21:96:21 | access to parameter b | +| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:85:21:85:21 | access to parameter b | | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | | LocalDataFlow.cs:52:21:52:34 | "taint source" | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | | LocalDataFlow.cs:53:15:53:19 | [post] access to local variable sink0 | LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | @@ -38,567 +37,396 @@ | LocalDataFlow.cs:60:21:60:25 | "abc" | LocalDataFlow.cs:60:13:60:25 | SSA def(sink1) | | LocalDataFlow.cs:61:9:61:22 | ... + ... | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | -| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | -| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | -| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | +| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | +| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | +| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | | LocalDataFlow.cs:65:9:65:25 | ... + ... | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | -| LocalDataFlow.cs:69:21:69:51 | object creation of type Dictionary | LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | -| LocalDataFlow.cs:70:9:70:13 | [post] access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | -| LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:74:24:74:55 | object creation of type Dictionary | LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | -| LocalDataFlow.cs:75:9:75:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:24:75:31 | [post] access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:76:9:76:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:18:76:22 | [post] access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | -| LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | -| LocalDataFlow.cs:80:21:80:32 | ... + ... | LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | -| LocalDataFlow.cs:81:15:81:19 | [post] access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:84:20:84:36 | ... + ... | LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:85:15:85:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | -| LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | -| LocalDataFlow.cs:89:15:89:19 | [post] access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | LocalDataFlow.cs:93:15:93:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): false] access to parameter b | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): true] access to parameter b | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | -| LocalDataFlow.cs:96:25:96:27 | [b (line 49): true] "a" | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:24:100:28 | "abc" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | -| LocalDataFlow.cs:100:32:100:36 | "def" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | -| LocalDataFlow.cs:101:15:101:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | -| LocalDataFlow.cs:104:21:104:33 | (...) ... | LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | -| LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | LocalDataFlow.cs:104:21:104:33 | (...) ... | -| LocalDataFlow.cs:105:15:105:19 | [post] access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | LocalDataFlow.cs:109:15:109:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:108:24:108:39 | (...) ... | LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:108:24:108:39 | (...) ... | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:35 | ... as ... | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | -| LocalDataFlow.cs:112:21:112:35 | ... as ... | LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | -| LocalDataFlow.cs:113:15:113:19 | [post] access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | LocalDataFlow.cs:117:15:117:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:37 | ... as ... | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:116:20:116:37 | ... as ... | LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | -| LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | -| LocalDataFlow.cs:120:22:120:43 | array creation of type Object[] | LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | -| LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | -| LocalDataFlow.cs:121:15:121:20 | [post] access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | -| LocalDataFlow.cs:124:24:124:42 | array creation of type Object[] | LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | -| LocalDataFlow.cs:124:39:124:40 | 42 | LocalDataFlow.cs:124:39:124:40 | (...) ... | -| LocalDataFlow.cs:125:15:125:22 | [post] access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | -| LocalDataFlow.cs:128:22:128:69 | object creation of type Dictionary | LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | -| LocalDataFlow.cs:128:61:128:65 | [post] access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:129:15:129:20 | [post] access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:132:20:132:67 | object creation of type Dictionary | LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | -| LocalDataFlow.cs:132:55:132:59 | [post] access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:133:15:133:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | LocalDataFlow.cs:137:15:137:20 | access to local variable sink14 | -| LocalDataFlow.cs:136:22:136:27 | [post] access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:55 | call to method First | LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | -| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:40:136:40 | access to parameter x | -| LocalDataFlow.cs:136:40:136:40 | access to parameter x | LocalDataFlow.cs:136:40:136:46 | access to property Value | -| LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | LocalDataFlow.cs:206:33:206:40 | access to local variable nonSink3 | -| LocalDataFlow.cs:140:20:140:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:55 | (...) ... | LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | -| LocalDataFlow.cs:140:20:140:55 | call to method First | LocalDataFlow.cs:140:20:140:55 | (...) ... | -| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:40:140:40 | access to parameter x | -| LocalDataFlow.cs:140:40:140:40 | access to parameter x | LocalDataFlow.cs:140:40:140:46 | access to property Value | -| LocalDataFlow.cs:141:15:141:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | -| LocalDataFlow.cs:144:22:144:39 | call to method Parse | LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | -| LocalDataFlow.cs:144:34:144:38 | [post] access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | LocalDataFlow.cs:196:22:196:27 | access to local variable sink15 | -| LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | LocalDataFlow.cs:148:15:148:20 | access to local variable sink16 | -| LocalDataFlow.cs:147:22:147:56 | call to method TryParse | LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | -| LocalDataFlow.cs:147:37:147:41 | [post] access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | LocalDataFlow.cs:150:15:150:20 | access to local variable sink17 | -| LocalDataFlow.cs:149:22:149:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:49 | call to method Replace | LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | -| LocalDataFlow.cs:149:44:149:48 | [post] access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | -| LocalDataFlow.cs:151:22:151:51 | call to method Format | LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | -| LocalDataFlow.cs:151:36:151:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:46:151:50 | [post] access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:152:15:152:20 | [post] access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | LocalDataFlow.cs:154:15:154:20 | access to local variable sink19 | -| LocalDataFlow.cs:153:22:153:52 | call to method Format | LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | -| LocalDataFlow.cs:153:44:153:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | LocalDataFlow.cs:156:15:156:20 | access to local variable sink45 | -| LocalDataFlow.cs:155:22:155:38 | call to method Parse | LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | -| LocalDataFlow.cs:155:33:155:37 | [post] access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | -| LocalDataFlow.cs:158:22:158:56 | call to method TryParse | LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | -| LocalDataFlow.cs:158:36:158:40 | [post] access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | LocalDataFlow.cs:160:37:160:42 | access to local variable sink46 | -| LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | -| LocalDataFlow.cs:160:22:160:43 | call to method ToByte | LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | -| LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | -| LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | -| LocalDataFlow.cs:162:22:162:46 | call to method Concat | LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | -| LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | (...) ... | -| LocalDataFlow.cs:163:15:163:20 | [post] access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | -| LocalDataFlow.cs:164:22:164:40 | call to method Copy | LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | -| LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | LocalDataFlow.cs:164:22:164:40 | call to method Copy | -| LocalDataFlow.cs:165:15:165:20 | [post] access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | -| LocalDataFlow.cs:166:22:166:54 | call to method Join | LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | -| LocalDataFlow.cs:167:15:167:20 | [post] access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | LocalDataFlow.cs:169:15:169:20 | access to local variable sink52 | -| LocalDataFlow.cs:168:22:168:41 | call to method Insert | LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | -| LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | LocalDataFlow.cs:173:15:173:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:172:20:172:40 | call to method Parse | LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | -| LocalDataFlow.cs:172:32:172:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | LocalDataFlow.cs:175:15:175:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:174:24:174:61 | call to method TryParse | LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | -| LocalDataFlow.cs:174:39:174:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:50 | call to method Replace | LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | -| LocalDataFlow.cs:177:15:177:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:20:178:52 | call to method Format | LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | -| LocalDataFlow.cs:178:34:178:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:179:15:179:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | LocalDataFlow.cs:181:15:181:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:180:20:180:39 | call to method Parse | LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | -| LocalDataFlow.cs:180:31:180:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:182:20:182:57 | call to method TryParse | LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | -| LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | -| LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | LocalDataFlow.cs:185:15:185:23 | access to local variable nonSink14 | -| LocalDataFlow.cs:184:25:184:48 | call to method ToByte | LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | -| LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | -| LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:186:20:186:46 | call to method Concat | LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | -| LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | (...) ... | -| LocalDataFlow.cs:187:15:187:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:20:188:40 | call to method Copy | LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | LocalDataFlow.cs:188:20:188:40 | call to method Copy | -| LocalDataFlow.cs:189:15:189:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:20:190:54 | call to method Join | LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | -| LocalDataFlow.cs:191:15:191:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | LocalDataFlow.cs:193:15:193:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:20:192:41 | call to method Insert | LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | -| LocalDataFlow.cs:196:22:196:32 | ... > ... | LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | -| LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | LocalDataFlow.cs:226:22:226:27 | access to local variable sink20 | -| LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | LocalDataFlow.cs:199:15:199:20 | access to local variable sink21 | -| LocalDataFlow.cs:198:22:198:40 | call to method Equals | LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | -| LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | LocalDataFlow.cs:201:15:201:20 | access to local variable sink22 | -| LocalDataFlow.cs:200:22:200:26 | [post] access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:45 | call to method Equals | LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | -| LocalDataFlow.cs:200:43:200:44 | 41 | LocalDataFlow.cs:200:35:200:44 | (...) ... | -| LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | LocalDataFlow.cs:205:15:205:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:204:20:204:24 | [post] access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:38 | call to method Equals | LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | -| LocalDataFlow.cs:204:33:204:37 | [post] access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:206:20:206:41 | call to method Equals | LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | -| LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | LocalDataFlow.cs:230:20:230:27 | access to local variable nonSink7 | -| LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | -| LocalDataFlow.cs:210:22:210:31 | access to indexer | LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | -| LocalDataFlow.cs:211:15:211:20 | [post] access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:214:20:214:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:31 | access to indexer | LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | -| LocalDataFlow.cs:215:15:215:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | LocalDataFlow.cs:219:15:219:20 | access to local variable sink24 | -| LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | -| LocalDataFlow.cs:218:22:218:30 | access to array element | LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | -| LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | LocalDataFlow.cs:223:15:223:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | -| LocalDataFlow.cs:222:20:222:30 | access to array element | LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | -| LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | LocalDataFlow.cs:227:15:227:20 | access to local variable sink25 | -| LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | -| LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | LocalDataFlow.cs:231:15:231:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | -| LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | -| LocalDataFlow.cs:234:22:234:43 | object creation of type Uri | LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | -| LocalDataFlow.cs:235:15:235:20 | [post] access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | LocalDataFlow.cs:237:15:237:20 | access to local variable sink27 | -| LocalDataFlow.cs:236:22:236:27 | [post] access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:38 | call to method ToString | LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | -| LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | LocalDataFlow.cs:239:15:239:20 | access to local variable sink28 | -| LocalDataFlow.cs:238:22:238:27 | [post] access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:40 | access to property PathAndQuery | LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | -| LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | LocalDataFlow.cs:241:15:241:20 | access to local variable sink29 | -| LocalDataFlow.cs:240:22:240:27 | [post] access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:33 | access to property Query | LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | -| LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | -| LocalDataFlow.cs:242:22:242:42 | access to property OriginalString | LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | -| LocalDataFlow.cs:243:15:243:20 | [post] access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | -| LocalDataFlow.cs:246:24:246:47 | object creation of type Uri | LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | -| LocalDataFlow.cs:247:15:247:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | LocalDataFlow.cs:249:15:249:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:248:20:248:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:38 | call to method ToString | LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | LocalDataFlow.cs:251:15:251:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:250:20:250:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:40 | access to property PathAndQuery | LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | LocalDataFlow.cs:253:15:253:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:252:20:252:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:33 | access to property Query | LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | -| LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:254:20:254:42 | access to property OriginalString | LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | -| LocalDataFlow.cs:255:15:255:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | -| LocalDataFlow.cs:258:22:258:55 | object creation of type StringReader | LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | -| LocalDataFlow.cs:259:15:259:20 | [post] access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | -| LocalDataFlow.cs:260:22:260:39 | call to method ReadToEnd | LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | -| LocalDataFlow.cs:261:15:261:20 | [post] access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | -| LocalDataFlow.cs:264:24:264:59 | object creation of type StringReader | LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | -| LocalDataFlow.cs:265:15:265:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:266:20:266:39 | call to method ReadToEnd | LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:267:15:267:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | -| LocalDataFlow.cs:270:22:270:127 | (...) ... | LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | -| LocalDataFlow.cs:270:30:270:119 | call to method Insert | LocalDataFlow.cs:270:30:270:127 | call to method Clone | -| LocalDataFlow.cs:270:30:270:127 | call to method Clone | LocalDataFlow.cs:270:22:270:127 | (...) ... | -| LocalDataFlow.cs:271:15:271:20 | [post] access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | LocalDataFlow.cs:273:15:273:20 | access to local variable sink48 | -| LocalDataFlow.cs:272:22:272:27 | [post] access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:63 | call to method Split | LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | -| LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:276:20:276:127 | (...) ... | LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | -| LocalDataFlow.cs:276:28:276:119 | call to method Insert | LocalDataFlow.cs:276:28:276:127 | call to method Clone | -| LocalDataFlow.cs:276:28:276:127 | call to method Clone | LocalDataFlow.cs:276:20:276:127 | (...) ... | -| LocalDataFlow.cs:277:15:277:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | LocalDataFlow.cs:279:15:279:23 | access to local variable nonSink15 | -| LocalDataFlow.cs:278:25:278:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:68 | call to method Split | LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | -| LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | -| LocalDataFlow.cs:282:22:282:46 | object creation of type StringBuilder | LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | -| LocalDataFlow.cs:283:15:283:20 | [post] access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | -| LocalDataFlow.cs:284:22:284:38 | call to method ToString | LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | -| LocalDataFlow.cs:285:15:285:20 | [post] access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | -| LocalDataFlow.cs:286:22:286:42 | object creation of type StringBuilder | LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | -| LocalDataFlow.cs:287:9:287:14 | [post] access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:291:25:291:51 | object creation of type StringBuilder | LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | -| LocalDataFlow.cs:292:15:292:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:293:20:293:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:39 | call to method ToString | LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:294:15:294:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:295:9:295:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | -| LocalDataFlow.cs:299:39:299:51 | [output] delegate creation of type Func | LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | -| LocalDataFlow.cs:299:39:299:51 | this access | LocalDataFlow.cs:309:42:309:57 | this access | -| LocalDataFlow.cs:300:15:300:20 | [post] access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:33 | access to property Value | -| LocalDataFlow.cs:301:22:301:33 | access to property Value | LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | -| LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | -| LocalDataFlow.cs:303:39:303:58 | [output] (...) => ... | LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | -| LocalDataFlow.cs:304:15:304:20 | [post] access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:33 | access to property Value | -| LocalDataFlow.cs:305:22:305:33 | access to property Value | LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | -| LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | -| LocalDataFlow.cs:309:42:309:57 | [output] delegate creation of type Func | LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | -| LocalDataFlow.cs:310:15:310:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | LocalDataFlow.cs:312:15:312:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:34 | access to property Value | -| LocalDataFlow.cs:311:20:311:34 | access to property Value | LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | -| LocalDataFlow.cs:313:38:313:45 | [output] (...) => ... | LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | -| LocalDataFlow.cs:314:15:314:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:34 | access to property Value | -| LocalDataFlow.cs:315:20:315:34 | access to property Value | LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:316:15:316:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | -| LocalDataFlow.cs:319:21:319:49 | object creation of type Dictionary | LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | -| LocalDataFlow.cs:320:9:320:13 | [post] access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:22:320:26 | [post] access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:321:15:321:19 | [post] access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | -| LocalDataFlow.cs:322:22:322:26 | [post] access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:33 | access to property Values | LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | -| LocalDataFlow.cs:323:15:323:20 | [post] access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | LocalDataFlow.cs:325:15:325:20 | access to local variable sink13 | -| LocalDataFlow.cs:324:22:324:37 | call to method Reverse | LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | -| LocalDataFlow.cs:328:9:328:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:22:329:26 | [post] access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:330:15:330:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | -| LocalDataFlow.cs:331:24:331:31 | [post] access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:38 | access to property Values | LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | -| LocalDataFlow.cs:332:15:332:22 | [post] access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | LocalDataFlow.cs:334:15:334:22 | access to local variable nonSink6 | -| LocalDataFlow.cs:333:24:333:41 | call to method Reverse | LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | -| LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:337:13:337:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:340:22:340:46 | access to property AList | -| LocalDataFlow.cs:337:35:337:52 | object creation of type DataContract | LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | -| LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | LocalDataFlow.cs:339:15:339:20 | access to local variable sink53 | -| LocalDataFlow.cs:338:22:338:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:48 | access to property AString | LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | -| LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | LocalDataFlow.cs:341:15:341:20 | access to local variable sink54 | -| LocalDataFlow.cs:340:22:340:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:46 | [post] access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:46 | access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:57 | access to property AString | LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | -| LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:345:20:345:41 | access to local variable nonTaintedDataContract | -| LocalDataFlow.cs:344:38:344:55 | object creation of type DataContract | LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | -| LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | LocalDataFlow.cs:346:15:346:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:345:20:345:49 | access to property AString | LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | -| LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | LocalDataFlow.cs:348:15:348:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:347:20:347:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:44 | access to property AnInt | LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | -| LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | LocalDataFlow.cs:350:15:350:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:349:20:349:53 | access to property AnInt | LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | -| LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:354:22:354:35 | access to local variable taintedTextBox | -| LocalDataFlow.cs:353:34:353:37 | null | LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | -| LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | LocalDataFlow.cs:355:15:355:20 | access to local variable sink60 | -| LocalDataFlow.cs:354:22:354:40 | access to property Text | LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | -| LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:359:20:359:36 | access to local variable nonTaintedTextBox | -| LocalDataFlow.cs:358:37:358:40 | null | LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | -| LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | LocalDataFlow.cs:360:15:360:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:359:20:359:41 | access to property Text | LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:363:22:363:27 | SSA def(sink61) | LocalDataFlow.cs:364:19:364:24 | access to local variable sink61 | -| LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | LocalDataFlow.cs:365:30:365:35 | access to local variable sink10 | -| LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | -| LocalDataFlow.cs:365:30:365:51 | call to method GetEnumerator | LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | -| LocalDataFlow.cs:366:15:366:20 | [post] access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | LocalDataFlow.cs:368:15:368:20 | access to local variable sink63 | -| LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:35 | access to property Current | -| LocalDataFlow.cs:367:22:367:35 | access to property Current | LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | -| LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | -| LocalDataFlow.cs:369:57:369:77 | (...) ... | LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | -| LocalDataFlow.cs:369:57:369:77 | call to method GetEnumerator | LocalDataFlow.cs:369:57:369:77 | (...) ... | -| LocalDataFlow.cs:370:15:370:20 | [post] access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | -| LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:35 | access to property Current | -| LocalDataFlow.cs:371:22:371:35 | access to property Current | LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | -| LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | -| LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | LocalDataFlow.cs:374:15:374:20 | access to local variable sink66 | -| LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:33 | access to property Value | -| LocalDataFlow.cs:373:22:373:33 | access to property Value | LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | -| LocalDataFlow.cs:377:22:377:30 | SSA def(nonSink17) | LocalDataFlow.cs:378:19:378:27 | access to local variable nonSink17 | -| LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | LocalDataFlow.cs:379:33:379:40 | access to local variable nonSink4 | -| LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | -| LocalDataFlow.cs:379:33:379:56 | call to method GetEnumerator | LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | -| LocalDataFlow.cs:380:15:380:23 | [post] access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | LocalDataFlow.cs:382:15:382:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:36 | access to property Current | -| LocalDataFlow.cs:381:20:381:36 | access to property Current | LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | -| LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | -| LocalDataFlow.cs:383:63:383:86 | (...) ... | LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | -| LocalDataFlow.cs:383:63:383:86 | call to method GetEnumerator | LocalDataFlow.cs:383:63:383:86 | (...) ... | -| LocalDataFlow.cs:384:15:384:23 | [post] access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | -| LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:41 | access to property Current | -| LocalDataFlow.cs:385:25:385:41 | access to property Current | LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | -| LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | -| LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | LocalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:34 | access to property Value | -| LocalDataFlow.cs:387:20:387:34 | access to property Value | LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:391:22:391:51 | call to method Run | LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | -| LocalDataFlow.cs:391:31:391:50 | [output] (...) => ... | LocalDataFlow.cs:391:22:391:51 | call to method Run | -| LocalDataFlow.cs:392:15:392:20 | [post] access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:393:22:393:33 | await ... | LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | -| LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | LocalDataFlow.cs:393:22:393:33 | await ... | -| LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | -| LocalDataFlow.cs:397:25:397:42 | call to method Run | LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | -| LocalDataFlow.cs:397:34:397:41 | [output] (...) => ... | LocalDataFlow.cs:397:25:397:42 | call to method Run | -| LocalDataFlow.cs:398:15:398:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:399:20:399:34 | await ... | LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | LocalDataFlow.cs:399:20:399:34 | await ... | -| LocalDataFlow.cs:400:15:400:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | LocalDataFlow.cs:404:15:404:20 | access to local variable sink69 | -| LocalDataFlow.cs:403:22:403:36 | $"..." | LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | -| LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:407:20:407:37 | $"..." | LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | -| LocalDataFlow.cs:408:15:408:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:411:22:411:34 | ... = ... | LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | ... = ... | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | -| LocalDataFlow.cs:412:15:412:20 | [post] access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:415:20:415:38 | ... = ... | LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | LocalDataFlow.cs:415:20:415:38 | ... = ... | -| LocalDataFlow.cs:416:15:416:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | -| LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | -| LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | LocalDataFlow.cs:424:19:424:27 | access to local variable nonSink16 | -| LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | -| LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | LocalDataFlow.cs:438:23:438:31 | access to local variable nonSink17 | -| LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:443:22:443:38 | ... ?? ... | LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:444:22:444:38 | ... ?? ... | LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | -| LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:464:28:464:30 | this | LocalDataFlow.cs:464:41:464:45 | this access | -| LocalDataFlow.cs:464:50:464:52 | this | LocalDataFlow.cs:464:56:464:60 | this access | -| LocalDataFlow.cs:464:50:464:52 | value | LocalDataFlow.cs:464:64:464:68 | access to parameter value | -| LocalDataFlow.cs:470:41:470:47 | tainted | LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | -| LocalDataFlow.cs:475:44:475:53 | nonTainted | LocalDataFlow.cs:477:15:477:24 | access to parameter nonTainted | -| LocalDataFlow.cs:480:44:480:44 | x | LocalDataFlow.cs:483:21:483:21 | access to parameter x | -| LocalDataFlow.cs:480:67:480:68 | os | LocalDataFlow.cs:486:32:486:33 | access to parameter os | -| LocalDataFlow.cs:483:21:483:21 | access to parameter x | LocalDataFlow.cs:483:16:483:21 | ... = ... | -| LocalDataFlow.cs:486:32:486:33 | access to parameter os | LocalDataFlow.cs:486:26:486:33 | ... = ... | -| LocalDataFlow.cs:491:41:491:44 | args | LocalDataFlow.cs:493:29:493:32 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | [post] access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | +| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | +| LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | +| LocalDataFlow.cs:69:21:69:32 | ... + ... | LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | +| LocalDataFlow.cs:70:15:70:19 | [post] access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:73:20:73:36 | ... + ... | LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:74:15:74:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | +| LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | +| LocalDataFlow.cs:78:15:78:19 | [post] access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | LocalDataFlow.cs:82:15:82:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): false] access to parameter b | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): true] access to parameter b | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | +| LocalDataFlow.cs:85:25:85:27 | [b (line 49): true] "a" | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:24:89:28 | "abc" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | +| LocalDataFlow.cs:89:32:89:36 | "def" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | +| LocalDataFlow.cs:90:15:90:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | +| LocalDataFlow.cs:93:21:93:33 | (...) ... | LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | +| LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | LocalDataFlow.cs:93:21:93:33 | (...) ... | +| LocalDataFlow.cs:94:15:94:19 | [post] access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | LocalDataFlow.cs:98:15:98:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:97:24:97:39 | (...) ... | LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:97:24:97:39 | (...) ... | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:35 | ... as ... | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | +| LocalDataFlow.cs:101:21:101:35 | ... as ... | LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | +| LocalDataFlow.cs:102:15:102:19 | [post] access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:37 | ... as ... | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:105:20:105:37 | ... as ... | LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | +| LocalDataFlow.cs:106:15:106:22 | [post] access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | +| LocalDataFlow.cs:109:22:109:39 | call to method Parse | LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | +| LocalDataFlow.cs:109:34:109:38 | [post] access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | LocalDataFlow.cs:161:22:161:27 | access to local variable sink15 | +| LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | LocalDataFlow.cs:113:15:113:20 | access to local variable sink16 | +| LocalDataFlow.cs:112:22:112:56 | call to method TryParse | LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | +| LocalDataFlow.cs:112:37:112:41 | [post] access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | LocalDataFlow.cs:115:15:115:20 | access to local variable sink17 | +| LocalDataFlow.cs:114:22:114:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:49 | call to method Replace | LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | +| LocalDataFlow.cs:114:44:114:48 | [post] access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | +| LocalDataFlow.cs:116:22:116:51 | call to method Format | LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | +| LocalDataFlow.cs:116:36:116:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:46:116:50 | [post] access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:117:15:117:20 | [post] access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | LocalDataFlow.cs:119:15:119:20 | access to local variable sink19 | +| LocalDataFlow.cs:118:22:118:52 | call to method Format | LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | +| LocalDataFlow.cs:118:44:118:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink45 | +| LocalDataFlow.cs:120:22:120:38 | call to method Parse | LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | +| LocalDataFlow.cs:120:33:120:37 | [post] access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | +| LocalDataFlow.cs:123:22:123:56 | call to method TryParse | LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | +| LocalDataFlow.cs:123:36:123:40 | [post] access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | +| LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | +| LocalDataFlow.cs:125:22:125:43 | call to method ToByte | LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | +| LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | +| LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | +| LocalDataFlow.cs:127:22:127:46 | call to method Concat | LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | +| LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | (...) ... | +| LocalDataFlow.cs:128:15:128:20 | [post] access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | +| LocalDataFlow.cs:129:22:129:40 | call to method Copy | LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | +| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | call to method Copy | +| LocalDataFlow.cs:130:15:130:20 | [post] access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | +| LocalDataFlow.cs:131:22:131:54 | call to method Join | LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | +| LocalDataFlow.cs:132:15:132:20 | [post] access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | LocalDataFlow.cs:134:15:134:20 | access to local variable sink52 | +| LocalDataFlow.cs:133:22:133:41 | call to method Insert | LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | +| LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | LocalDataFlow.cs:138:15:138:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:137:20:137:40 | call to method Parse | LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | +| LocalDataFlow.cs:137:32:137:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | LocalDataFlow.cs:140:15:140:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:139:24:139:61 | call to method TryParse | LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | +| LocalDataFlow.cs:139:39:139:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:50 | call to method Replace | LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | +| LocalDataFlow.cs:142:15:142:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:20:143:52 | call to method Format | LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | +| LocalDataFlow.cs:143:34:143:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:144:15:144:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | LocalDataFlow.cs:146:15:146:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:145:20:145:39 | call to method Parse | LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | +| LocalDataFlow.cs:145:31:145:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:147:20:147:57 | call to method TryParse | LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | +| LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | +| LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | LocalDataFlow.cs:150:15:150:23 | access to local variable nonSink14 | +| LocalDataFlow.cs:149:25:149:48 | call to method ToByte | LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | +| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | +| LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:151:20:151:46 | call to method Concat | LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | +| LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | (...) ... | +| LocalDataFlow.cs:152:15:152:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:20:153:40 | call to method Copy | LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | call to method Copy | +| LocalDataFlow.cs:154:15:154:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:20:155:54 | call to method Join | LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | +| LocalDataFlow.cs:156:15:156:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:20:157:41 | call to method Insert | LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:158:15:158:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | +| LocalDataFlow.cs:161:22:161:32 | ... > ... | LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | +| LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | LocalDataFlow.cs:175:22:175:27 | access to local variable sink20 | +| LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | LocalDataFlow.cs:164:15:164:20 | access to local variable sink21 | +| LocalDataFlow.cs:163:22:163:26 | [post] access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:40 | call to method Equals | LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | +| LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | LocalDataFlow.cs:166:15:166:20 | access to local variable sink22 | +| LocalDataFlow.cs:165:22:165:26 | [post] access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:45 | call to method Equals | LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | +| LocalDataFlow.cs:165:43:165:44 | 41 | LocalDataFlow.cs:165:35:165:44 | (...) ... | +| LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | LocalDataFlow.cs:170:15:170:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:169:20:169:24 | [post] access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:38 | call to method Equals | LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | +| LocalDataFlow.cs:169:33:169:37 | [post] access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:171:20:171:41 | call to method Equals | LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | +| LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | LocalDataFlow.cs:179:20:179:27 | access to local variable nonSink7 | +| LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | LocalDataFlow.cs:176:15:176:20 | access to local variable sink25 | +| LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | +| LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | LocalDataFlow.cs:180:15:180:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | +| LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | +| LocalDataFlow.cs:183:22:183:42 | object creation of type Uri | LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | +| LocalDataFlow.cs:184:15:184:20 | [post] access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | LocalDataFlow.cs:186:15:186:20 | access to local variable sink27 | +| LocalDataFlow.cs:185:22:185:27 | [post] access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:38 | call to method ToString | LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | +| LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | LocalDataFlow.cs:188:15:188:20 | access to local variable sink28 | +| LocalDataFlow.cs:187:22:187:27 | [post] access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery | LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | +| LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | LocalDataFlow.cs:190:15:190:20 | access to local variable sink29 | +| LocalDataFlow.cs:189:22:189:27 | [post] access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:33 | access to property Query | LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | +| LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | +| LocalDataFlow.cs:191:22:191:42 | access to property OriginalString | LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | +| LocalDataFlow.cs:192:15:192:20 | [post] access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | +| LocalDataFlow.cs:195:24:195:47 | object creation of type Uri | LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | +| LocalDataFlow.cs:196:15:196:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | LocalDataFlow.cs:198:15:198:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:197:20:197:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:38 | call to method ToString | LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | LocalDataFlow.cs:200:15:200:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:199:20:199:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery | LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | LocalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:201:20:201:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:33 | access to property Query | LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | +| LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:203:20:203:42 | access to property OriginalString | LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | +| LocalDataFlow.cs:204:15:204:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | +| LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader | LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | +| LocalDataFlow.cs:208:15:208:20 | [post] access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | +| LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd | LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | +| LocalDataFlow.cs:210:15:210:20 | [post] access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | +| LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader | LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | +| LocalDataFlow.cs:214:15:214:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd | LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:216:15:216:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | +| LocalDataFlow.cs:219:22:219:127 | (...) ... | LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | +| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | call to method Clone | +| LocalDataFlow.cs:219:30:219:127 | call to method Clone | LocalDataFlow.cs:219:22:219:127 | (...) ... | +| LocalDataFlow.cs:220:15:220:20 | [post] access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | LocalDataFlow.cs:222:15:222:20 | access to local variable sink48 | +| LocalDataFlow.cs:221:22:221:27 | [post] access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:63 | call to method Split | LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | +| LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:225:20:225:127 | (...) ... | LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | +| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | call to method Clone | +| LocalDataFlow.cs:225:28:225:127 | call to method Clone | LocalDataFlow.cs:225:20:225:127 | (...) ... | +| LocalDataFlow.cs:226:15:226:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | LocalDataFlow.cs:228:15:228:23 | access to local variable nonSink15 | +| LocalDataFlow.cs:227:25:227:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:68 | call to method Split | LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | +| LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | +| LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder | LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | +| LocalDataFlow.cs:232:15:232:20 | [post] access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | +| LocalDataFlow.cs:233:22:233:38 | call to method ToString | LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | +| LocalDataFlow.cs:234:15:234:20 | [post] access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | +| LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder | LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | +| LocalDataFlow.cs:236:9:236:14 | [post] access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder | LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | +| LocalDataFlow.cs:241:15:241:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:242:20:242:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:39 | call to method ToString | LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:243:15:243:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:244:9:244:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:248:13:248:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:251:22:251:46 | access to property AList | +| LocalDataFlow.cs:248:35:248:52 | object creation of type DataContract | LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | +| LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | LocalDataFlow.cs:250:15:250:20 | access to local variable sink53 | +| LocalDataFlow.cs:249:22:249:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:48 | access to property AString | LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | +| LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | LocalDataFlow.cs:252:15:252:20 | access to local variable sink54 | +| LocalDataFlow.cs:251:22:251:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:46 | [post] access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:57 | access to property AString | LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | +| LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | +| LocalDataFlow.cs:255:38:255:55 | object creation of type DataContract | LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | +| LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | LocalDataFlow.cs:257:15:257:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:256:20:256:49 | access to property AString | LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | +| LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | LocalDataFlow.cs:259:15:259:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:258:20:258:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:44 | access to property AnInt | LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | +| LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | LocalDataFlow.cs:261:15:261:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:260:20:260:53 | access to property AnInt | LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | +| LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | +| LocalDataFlow.cs:264:34:264:37 | null | LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | +| LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | LocalDataFlow.cs:266:15:266:20 | access to local variable sink60 | +| LocalDataFlow.cs:265:22:265:40 | access to property Text | LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | +| LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | +| LocalDataFlow.cs:269:37:269:40 | null | LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | +| LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | LocalDataFlow.cs:271:15:271:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:270:20:270:41 | access to property Text | LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:274:22:274:51 | call to method Run | LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | +| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | call to method Run | +| LocalDataFlow.cs:275:15:275:20 | [post] access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:276:22:276:33 | await ... | LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | +| LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | LocalDataFlow.cs:276:22:276:33 | await ... | +| LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | +| LocalDataFlow.cs:280:25:280:42 | call to method Run | LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | +| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | call to method Run | +| LocalDataFlow.cs:281:15:281:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:282:20:282:34 | await ... | LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | +| LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | LocalDataFlow.cs:282:20:282:34 | await ... | +| LocalDataFlow.cs:283:15:283:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | LocalDataFlow.cs:287:15:287:20 | access to local variable sink69 | +| LocalDataFlow.cs:286:22:286:36 | $"..." | LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | +| LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:290:20:290:37 | $"..." | LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | +| LocalDataFlow.cs:291:15:291:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:294:22:294:34 | ... = ... | LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | ... = ... | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | +| LocalDataFlow.cs:295:15:295:20 | [post] access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:298:20:298:38 | ... = ... | LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | LocalDataFlow.cs:298:20:298:38 | ... = ... | +| LocalDataFlow.cs:299:15:299:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | +| LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | +| LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | LocalDataFlow.cs:307:19:307:27 | access to local variable nonSink16 | +| LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | +| LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | LocalDataFlow.cs:321:23:321:31 | access to local variable nonSink17 | +| LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:326:22:326:38 | ... ?? ... | LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:327:22:327:38 | ... ?? ... | LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | +| LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:347:28:347:30 | this | LocalDataFlow.cs:347:41:347:45 | this access | +| LocalDataFlow.cs:347:50:347:52 | this | LocalDataFlow.cs:347:56:347:60 | this access | +| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:64:347:68 | access to parameter value | +| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | +| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:360:15:360:24 | access to parameter nonTainted | +| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:366:21:366:21 | access to parameter x | +| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:369:32:369:33 | access to parameter os | +| LocalDataFlow.cs:366:21:366:21 | access to parameter x | LocalDataFlow.cs:366:16:366:21 | ... = ... | +| LocalDataFlow.cs:369:32:369:33 | access to parameter os | LocalDataFlow.cs:369:26:369:33 | ... = ... | +| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:376:29:376:32 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | [post] access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | | SSA.cs:5:17:5:17 | SSA entry def(this.S) | SSA.cs:67:9:67:14 | access to field S | | SSA.cs:5:17:5:17 | this | SSA.cs:67:9:67:12 | this access | | SSA.cs:5:26:5:32 | tainted | SSA.cs:8:24:8:30 | access to parameter tainted | diff --git a/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs b/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs index 6603abc50f1..eea36528104 100644 --- a/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs @@ -65,17 +65,6 @@ public class LocalDataFlow nonSink0 += "abc"; Check(nonSink0); - // Assignment (indexer), tainted - var sink2 = new Dictionary(); - sink2[0][1] = sink1; - Check(sink2); - - // Assignment (indexer), not tainted - var nonSink1 = new Dictionary(); - nonSink1[""] = nonSink0; - nonSink1[sink1] = ""; // do not track tainted keys - Check(nonSink1); - // Concatenation, tainted var sink5 = sink1 + "ok"; Check(sink5); @@ -116,30 +105,6 @@ public class LocalDataFlow nonSink3 = nonSink0 as object; Check(nonSink3); - // Array creation (initializer), tainted - var sink10 = new object[] { sink9 }; - Check(sink10); - - // Array creation (initializer), not tainted - var nonSink4 = new object[] { 42 }; - Check(nonSink4); - - // Object creation (collection initializer), tainted - var sink11 = new Dictionary { { "", sink9 } }; - Check(sink11); - - // Object creation (collection initializer), not tainted - nonSink1 = new Dictionary { { sink9, "" } }; - Check(nonSink1); - - // Data-preserving LINQ, tainted - var sink14 = sink11.First(x => x.Value != null); - Check(sink14); - - // Data-preserving LINQ, not tainted - nonSink3 = nonSink1.First(x => x.Value != null); - Check(nonSink1); - // Standard method with a tainted argument, tainted var sink15 = Int32.Parse(sink9); Check(sink15); @@ -206,22 +171,6 @@ public class LocalDataFlow nonSink7 = sink8.Equals(nonSink3); Check(nonSink7); - // Indexer access, tainted - var sink23 = sink11[""]; - Check(sink23); - - // Indexer access, not tainted - nonSink0 = nonSink1[""]; - Check(nonSink0); - - // Array access, tainted - var sink24 = sink10[0]; - Check(sink24); - - // Array access, not tainted - nonSink3 = nonSink4[0]; - Check(nonSink3); - // Logical operation using tainted operand, tainted var sink25 = sink20 || false; Check(sink25); @@ -231,7 +180,7 @@ public class LocalDataFlow Check(nonSink7); // Ad hoc tracking (System.Uri), tainted - var sink26 = new System.Uri(sink23); + var sink26 = new System.Uri(sink9); Check(sink26); var sink27 = sink26.ToString(); Check(sink27); @@ -295,44 +244,6 @@ public class LocalDataFlow nonSink10.AppendLine(nonSink0); Check(nonSink10); - // Ad hoc tracking (System.Lazy), tainted - var sink40 = new Lazy(TaintedMethod); - Check(sink40); - var sink41 = sink40.Value; - Check(sink41); - var sink42 = new Lazy(() => "taint source"); - Check(sink42); - var sink43 = sink42.Value; - Check(sink43); - - // Ad hoc tracking (System.Lazy), not tainted - var nonSink12 = new Lazy(NonTaintedMethod); - Check(nonSink12); - nonSink0 = nonSink12.Value; - Check(nonSink0); - nonSink12 = new Lazy(() => ""); - Check(nonSink12); - nonSink0 = nonSink12.Value; - Check(nonSink0); - - // Ad hoc tracking (collections), tainted - var sink3 = new Dictionary(); - sink3.Add(0, sink1); - Check(sink3); - var sink12 = sink3.Values; - Check(sink12); - var sink13 = sink12.Reverse(); - Check(sink13); - - // Ad hoc tracking (collections), not tainted - nonSink1.Add("", nonSink0); - nonSink1.Add(sink1, ""); // do not track tainted keys - Check(nonSink1); - var nonSink5 = nonSink1.Values; - Check(nonSink5); - var nonSink6 = nonSink5.Reverse(); - Check(nonSink6); - // Ad hoc tracking (data contracts), tainted var taintedDataContract = new DataContract(); var sink53 = taintedDataContract.AString; @@ -359,34 +270,6 @@ public class LocalDataFlow nonSink0 = nonTaintedTextBox.Text; Check(nonSink0); - // Iteration over a tracked expression, tainted - foreach (var sink61 in sink10) - Check(sink61); - IEnumerator sink62 = sink10.GetEnumerator(); - Check(sink62); - var sink63 = sink62.Current; - Check(sink63); - IEnumerator> sink64 = sink3.GetEnumerator(); - Check(sink64); - var sink65 = sink64.Current; - Check(sink65); - var sink66 = sink65.Value; - Check(sink66); - - // Iteration over a tracked expression, not tainted - foreach (var nonSink17 in nonSink4) - Check(nonSink17); - IEnumerator nonSink18 = nonSink4.GetEnumerator(); - Check(nonSink18); - nonSink3 = nonSink18.Current; - Check(nonSink3); - IEnumerator> nonSink19 = nonSink1.GetEnumerator(); - Check(nonSink19); - var nonSink20 = nonSink19.Current; - Check(nonSink20); - nonSink0 = nonSink20.Value; - Check(nonSink0); - // async await, tainted var sink67 = Task.Run(() => "taint source"); Check(sink67); diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected index 756d79333c1..e8a0153dc92 100644 --- a/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected +++ b/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected @@ -1,70 +1,51 @@ | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | | LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | -| LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | -| LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | -| LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | -| LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | -| LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | -| LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | -| LocalDataFlow.cs:137:15:137:20 | access to local variable sink14 | -| LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | -| LocalDataFlow.cs:148:15:148:20 | access to local variable sink16 | -| LocalDataFlow.cs:150:15:150:20 | access to local variable sink17 | -| LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | -| LocalDataFlow.cs:154:15:154:20 | access to local variable sink19 | -| LocalDataFlow.cs:156:15:156:20 | access to local variable sink45 | -| LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | -| LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | -| LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | -| LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | -| LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | -| LocalDataFlow.cs:169:15:169:20 | access to local variable sink52 | -| LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | -| LocalDataFlow.cs:199:15:199:20 | access to local variable sink21 | -| LocalDataFlow.cs:201:15:201:20 | access to local variable sink22 | -| LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | -| LocalDataFlow.cs:219:15:219:20 | access to local variable sink24 | -| LocalDataFlow.cs:227:15:227:20 | access to local variable sink25 | -| LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | -| LocalDataFlow.cs:237:15:237:20 | access to local variable sink27 | -| LocalDataFlow.cs:239:15:239:20 | access to local variable sink28 | -| LocalDataFlow.cs:241:15:241:20 | access to local variable sink29 | -| LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | -| LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | -| LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | -| LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | -| LocalDataFlow.cs:273:15:273:20 | access to local variable sink48 | -| LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | -| LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | -| LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | -| LocalDataFlow.cs:325:15:325:20 | access to local variable sink13 | -| LocalDataFlow.cs:339:15:339:20 | access to local variable sink53 | -| LocalDataFlow.cs:341:15:341:20 | access to local variable sink54 | -| LocalDataFlow.cs:355:15:355:20 | access to local variable sink60 | -| LocalDataFlow.cs:364:19:364:24 | access to local variable sink61 | -| LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | -| LocalDataFlow.cs:368:15:368:20 | access to local variable sink63 | -| LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | -| LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | -| LocalDataFlow.cs:374:15:374:20 | access to local variable sink66 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:404:15:404:20 | access to local variable sink69 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | +| LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | +| LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | +| LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | +| LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | +| LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | +| LocalDataFlow.cs:113:15:113:20 | access to local variable sink16 | +| LocalDataFlow.cs:115:15:115:20 | access to local variable sink17 | +| LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | +| LocalDataFlow.cs:119:15:119:20 | access to local variable sink19 | +| LocalDataFlow.cs:121:15:121:20 | access to local variable sink45 | +| LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | +| LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | +| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | +| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | +| LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | +| LocalDataFlow.cs:134:15:134:20 | access to local variable sink52 | +| LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | +| LocalDataFlow.cs:164:15:164:20 | access to local variable sink21 | +| LocalDataFlow.cs:166:15:166:20 | access to local variable sink22 | +| LocalDataFlow.cs:176:15:176:20 | access to local variable sink25 | +| LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | +| LocalDataFlow.cs:186:15:186:20 | access to local variable sink27 | +| LocalDataFlow.cs:188:15:188:20 | access to local variable sink28 | +| LocalDataFlow.cs:190:15:190:20 | access to local variable sink29 | +| LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | +| LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | +| LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | +| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | +| LocalDataFlow.cs:222:15:222:20 | access to local variable sink48 | +| LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | +| LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | +| LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:250:15:250:20 | access to local variable sink53 | +| LocalDataFlow.cs:252:15:252:20 | access to local variable sink54 | +| LocalDataFlow.cs:266:15:266:20 | access to local variable sink60 | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:287:15:287:20 | access to local variable sink69 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | | SSA.cs:9:15:9:22 | access to local variable ssaSink0 | | SSA.cs:25:15:25:22 | access to local variable ssaSink1 | | SSA.cs:43:15:43:22 | access to local variable ssaSink2 | diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected index 8dd765a23cd..4cb33d841cb 100644 --- a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected @@ -24,9 +24,8 @@ | Capture.cs:58:21:58:21 | 1 | Capture.cs:58:17:58:21 | SSA def(i) | | Capture.cs:61:17:61:17 | 1 | Capture.cs:61:13:61:17 | SSA def(i) | | Capture.cs:63:9:63:17 | SSA call def(i) | Capture.cs:64:13:64:13 | access to local variable i | -| LocalDataFlow.cs:49:23:49:23 | this | LocalDataFlow.cs:299:39:299:51 | this access | | LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:49:30:49:30 | b | -| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:96:21:96:21 | access to parameter b | +| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:85:21:85:21 | access to parameter b | | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | | LocalDataFlow.cs:52:21:52:34 | "taint source" | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | | LocalDataFlow.cs:53:15:53:19 | [post] access to local variable sink0 | LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | @@ -41,713 +40,508 @@ | LocalDataFlow.cs:61:9:61:22 | ... + ... | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | | LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:61:9:61:22 | ... + ... | -| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | -| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | -| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | +| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | +| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | +| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | | LocalDataFlow.cs:65:9:65:16 | access to local variable nonSink0 | LocalDataFlow.cs:65:9:65:25 | ... + ... | | LocalDataFlow.cs:65:9:65:25 | ... + ... | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | | LocalDataFlow.cs:65:21:65:25 | "abc" | LocalDataFlow.cs:65:9:65:25 | ... + ... | -| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | -| LocalDataFlow.cs:69:21:69:51 | object creation of type Dictionary | LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | -| LocalDataFlow.cs:70:9:70:13 | [post] access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | LocalDataFlow.cs:70:9:70:16 | access to indexer | -| LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:70:9:70:16 | access to indexer | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | -| LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:74:24:74:55 | object creation of type Dictionary | LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | -| LocalDataFlow.cs:75:9:75:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | LocalDataFlow.cs:75:9:75:20 | access to indexer | -| LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:24:75:31 | [post] access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:76:9:76:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:23 | access to indexer | -| LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:18:76:22 | [post] access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:76:27:76:28 | "" | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | -| LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | LocalDataFlow.cs:80:21:80:32 | ... + ... | -| LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | -| LocalDataFlow.cs:80:21:80:32 | ... + ... | LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | -| LocalDataFlow.cs:80:29:80:32 | "ok" | LocalDataFlow.cs:80:21:80:32 | ... + ... | -| LocalDataFlow.cs:81:15:81:19 | [post] access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:36 | ... + ... | -| LocalDataFlow.cs:84:20:84:36 | ... + ... | LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:84:31:84:36 | "test" | LocalDataFlow.cs:84:20:84:36 | ... + ... | -| LocalDataFlow.cs:85:15:85:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | -| LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | -| LocalDataFlow.cs:89:15:89:19 | [post] access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | LocalDataFlow.cs:93:15:93:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): false] access to parameter b | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): true] access to parameter b | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | -| LocalDataFlow.cs:96:25:96:27 | [b (line 49): true] "a" | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:24:100:28 | "abc" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | -| LocalDataFlow.cs:100:32:100:36 | "def" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | -| LocalDataFlow.cs:101:15:101:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | -| LocalDataFlow.cs:104:21:104:33 | (...) ... | LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | -| LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | LocalDataFlow.cs:104:21:104:33 | (...) ... | -| LocalDataFlow.cs:105:15:105:19 | [post] access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | LocalDataFlow.cs:109:15:109:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:108:24:108:39 | (...) ... | LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:108:24:108:39 | (...) ... | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:35 | ... as ... | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | -| LocalDataFlow.cs:112:21:112:35 | ... as ... | LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | -| LocalDataFlow.cs:113:15:113:19 | [post] access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | LocalDataFlow.cs:117:15:117:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:37 | ... as ... | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:116:20:116:37 | ... as ... | LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | -| LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | -| LocalDataFlow.cs:120:22:120:43 | array creation of type Object[] | LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | -| LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | LocalDataFlow.cs:120:22:120:43 | array creation of type Object[] | -| LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | -| LocalDataFlow.cs:121:15:121:20 | [post] access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | -| LocalDataFlow.cs:124:24:124:42 | array creation of type Object[] | LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | -| LocalDataFlow.cs:124:39:124:40 | 42 | LocalDataFlow.cs:124:39:124:40 | (...) ... | -| LocalDataFlow.cs:124:39:124:40 | (...) ... | LocalDataFlow.cs:124:24:124:42 | array creation of type Object[] | -| LocalDataFlow.cs:125:15:125:22 | [post] access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | -| LocalDataFlow.cs:128:22:128:69 | object creation of type Dictionary | LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | -| LocalDataFlow.cs:128:61:128:65 | [post] access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | LocalDataFlow.cs:128:22:128:69 | object creation of type Dictionary | -| LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:129:15:129:20 | [post] access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:132:20:132:67 | object creation of type Dictionary | LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | -| LocalDataFlow.cs:132:55:132:59 | [post] access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:132:62:132:63 | "" | LocalDataFlow.cs:132:20:132:67 | object creation of type Dictionary | -| LocalDataFlow.cs:133:15:133:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | LocalDataFlow.cs:137:15:137:20 | access to local variable sink14 | -| LocalDataFlow.cs:136:22:136:27 | [post] access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | LocalDataFlow.cs:136:22:136:55 | call to method First | -| LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:55 | call to method First | LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | -| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:35:136:35 | x | -| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:40:136:40 | access to parameter x | -| LocalDataFlow.cs:136:40:136:40 | access to parameter x | LocalDataFlow.cs:136:40:136:46 | access to property Value | -| LocalDataFlow.cs:136:40:136:46 | access to property Value | LocalDataFlow.cs:136:40:136:54 | ... != ... | -| LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | LocalDataFlow.cs:206:33:206:40 | access to local variable nonSink3 | -| LocalDataFlow.cs:140:20:140:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:55 | call to method First | -| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:55 | (...) ... | LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | -| LocalDataFlow.cs:140:20:140:55 | call to method First | LocalDataFlow.cs:140:20:140:55 | (...) ... | -| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:35:140:35 | x | -| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:40:140:40 | access to parameter x | -| LocalDataFlow.cs:140:40:140:40 | access to parameter x | LocalDataFlow.cs:140:40:140:46 | access to property Value | -| LocalDataFlow.cs:140:40:140:46 | access to property Value | LocalDataFlow.cs:140:40:140:54 | ... != ... | -| LocalDataFlow.cs:141:15:141:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | -| LocalDataFlow.cs:144:22:144:39 | call to method Parse | LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | -| LocalDataFlow.cs:144:34:144:38 | [post] access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | LocalDataFlow.cs:144:22:144:39 | call to method Parse | -| LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | LocalDataFlow.cs:196:22:196:27 | access to local variable sink15 | -| LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | LocalDataFlow.cs:148:15:148:20 | access to local variable sink16 | -| LocalDataFlow.cs:147:22:147:56 | call to method TryParse | LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | -| LocalDataFlow.cs:147:37:147:41 | [post] access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | LocalDataFlow.cs:147:22:147:56 | call to method TryParse | -| LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | LocalDataFlow.cs:150:15:150:20 | access to local variable sink17 | -| LocalDataFlow.cs:149:22:149:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | LocalDataFlow.cs:149:22:149:49 | call to method Replace | -| LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:49 | call to method Replace | LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | -| LocalDataFlow.cs:149:44:149:48 | [post] access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | LocalDataFlow.cs:149:22:149:49 | call to method Replace | -| LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | -| LocalDataFlow.cs:151:22:151:51 | call to method Format | LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | -| LocalDataFlow.cs:151:36:151:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | LocalDataFlow.cs:151:22:151:51 | call to method Format | -| LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:46:151:50 | [post] access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | LocalDataFlow.cs:151:22:151:51 | call to method Format | -| LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:152:15:152:20 | [post] access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | LocalDataFlow.cs:154:15:154:20 | access to local variable sink19 | -| LocalDataFlow.cs:153:22:153:52 | call to method Format | LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | -| LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | LocalDataFlow.cs:153:22:153:52 | call to method Format | -| LocalDataFlow.cs:153:44:153:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | LocalDataFlow.cs:153:22:153:52 | call to method Format | -| LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | LocalDataFlow.cs:156:15:156:20 | access to local variable sink45 | -| LocalDataFlow.cs:155:22:155:38 | call to method Parse | LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | -| LocalDataFlow.cs:155:33:155:37 | [post] access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | LocalDataFlow.cs:155:22:155:38 | call to method Parse | -| LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | -| LocalDataFlow.cs:158:22:158:56 | call to method TryParse | LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | -| LocalDataFlow.cs:158:36:158:40 | [post] access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | LocalDataFlow.cs:158:22:158:56 | call to method TryParse | -| LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | LocalDataFlow.cs:160:37:160:42 | access to local variable sink46 | -| LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | -| LocalDataFlow.cs:160:22:160:43 | call to method ToByte | LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | -| LocalDataFlow.cs:160:37:160:42 | access to local variable sink46 | LocalDataFlow.cs:160:22:160:43 | call to method ToByte | -| LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | -| LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | -| LocalDataFlow.cs:162:22:162:46 | call to method Concat | LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | -| LocalDataFlow.cs:162:36:162:37 | "" | LocalDataFlow.cs:162:22:162:46 | call to method Concat | -| LocalDataFlow.cs:162:40:162:45 | (...) ... | LocalDataFlow.cs:162:22:162:46 | call to method Concat | -| LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | (...) ... | -| LocalDataFlow.cs:163:15:163:20 | [post] access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | -| LocalDataFlow.cs:164:22:164:40 | call to method Copy | LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | -| LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | LocalDataFlow.cs:164:22:164:40 | call to method Copy | -| LocalDataFlow.cs:165:15:165:20 | [post] access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | -| LocalDataFlow.cs:166:22:166:54 | call to method Join | LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | -| LocalDataFlow.cs:166:34:166:37 | ", " | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:166:40:166:41 | "" | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:166:52:166:53 | "" | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:167:15:167:20 | [post] access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | LocalDataFlow.cs:169:15:169:20 | access to local variable sink52 | -| LocalDataFlow.cs:168:22:168:23 | "" | LocalDataFlow.cs:168:22:168:41 | call to method Insert | -| LocalDataFlow.cs:168:22:168:41 | call to method Insert | LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | -| LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | LocalDataFlow.cs:168:22:168:41 | call to method Insert | -| LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | LocalDataFlow.cs:173:15:173:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:172:20:172:40 | call to method Parse | LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | -| LocalDataFlow.cs:172:32:172:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | LocalDataFlow.cs:172:20:172:40 | call to method Parse | -| LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | LocalDataFlow.cs:175:15:175:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:174:24:174:61 | call to method TryParse | LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | -| LocalDataFlow.cs:174:39:174:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | LocalDataFlow.cs:174:24:174:61 | call to method TryParse | -| LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:50 | call to method Replace | -| LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:50 | call to method Replace | LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | -| LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:50 | call to method Replace | -| LocalDataFlow.cs:177:15:177:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:20:178:52 | call to method Format | LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | -| LocalDataFlow.cs:178:34:178:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | LocalDataFlow.cs:178:20:178:52 | call to method Format | -| LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | LocalDataFlow.cs:178:20:178:52 | call to method Format | -| LocalDataFlow.cs:179:15:179:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | LocalDataFlow.cs:181:15:181:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:180:20:180:39 | call to method Parse | LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | -| LocalDataFlow.cs:180:31:180:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | LocalDataFlow.cs:180:20:180:39 | call to method Parse | -| LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:182:20:182:57 | call to method TryParse | LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | -| LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | LocalDataFlow.cs:182:20:182:57 | call to method TryParse | -| LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | -| LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | LocalDataFlow.cs:185:15:185:23 | access to local variable nonSink14 | -| LocalDataFlow.cs:184:25:184:48 | call to method ToByte | LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | -| LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | LocalDataFlow.cs:184:25:184:48 | call to method ToByte | -| LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | -| LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:186:20:186:46 | call to method Concat | LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | -| LocalDataFlow.cs:186:34:186:35 | "" | LocalDataFlow.cs:186:20:186:46 | call to method Concat | -| LocalDataFlow.cs:186:38:186:45 | (...) ... | LocalDataFlow.cs:186:20:186:46 | call to method Concat | -| LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | (...) ... | -| LocalDataFlow.cs:187:15:187:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:20:188:40 | call to method Copy | LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | LocalDataFlow.cs:188:20:188:40 | call to method Copy | -| LocalDataFlow.cs:189:15:189:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:20:190:54 | call to method Join | LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | -| LocalDataFlow.cs:190:32:190:35 | ", " | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:190:38:190:39 | "" | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:190:52:190:53 | "" | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:191:15:191:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | LocalDataFlow.cs:193:15:193:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:20:192:21 | "" | LocalDataFlow.cs:192:20:192:41 | call to method Insert | -| LocalDataFlow.cs:192:20:192:41 | call to method Insert | LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | LocalDataFlow.cs:192:20:192:41 | call to method Insert | -| LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | -| LocalDataFlow.cs:196:22:196:27 | access to local variable sink15 | LocalDataFlow.cs:196:22:196:32 | ... > ... | -| LocalDataFlow.cs:196:22:196:32 | ... > ... | LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | -| LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | LocalDataFlow.cs:226:22:226:27 | access to local variable sink20 | -| LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | LocalDataFlow.cs:199:15:199:20 | access to local variable sink21 | -| LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | LocalDataFlow.cs:198:22:198:40 | call to method Equals | -| LocalDataFlow.cs:198:22:198:40 | call to method Equals | LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | -| LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | LocalDataFlow.cs:201:15:201:20 | access to local variable sink22 | -| LocalDataFlow.cs:200:22:200:26 | [post] access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | LocalDataFlow.cs:200:22:200:45 | call to method Equals | -| LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:45 | call to method Equals | LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | -| LocalDataFlow.cs:200:43:200:44 | 41 | LocalDataFlow.cs:200:35:200:44 | (...) ... | -| LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | LocalDataFlow.cs:205:15:205:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:204:20:204:24 | [post] access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:38 | call to method Equals | LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | -| LocalDataFlow.cs:204:33:204:37 | [post] access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:206:20:206:41 | call to method Equals | LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | -| LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | LocalDataFlow.cs:230:20:230:27 | access to local variable nonSink7 | -| LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | -| LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | LocalDataFlow.cs:210:22:210:31 | access to indexer | -| LocalDataFlow.cs:210:22:210:31 | access to indexer | LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | -| LocalDataFlow.cs:211:15:211:20 | [post] access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:214:20:214:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:31 | access to indexer | -| LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:31 | access to indexer | LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | -| LocalDataFlow.cs:215:15:215:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | LocalDataFlow.cs:219:15:219:20 | access to local variable sink24 | -| LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | LocalDataFlow.cs:218:22:218:30 | access to array element | -| LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | -| LocalDataFlow.cs:218:22:218:30 | access to array element | LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | -| LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | LocalDataFlow.cs:223:15:223:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:30 | access to array element | -| LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | -| LocalDataFlow.cs:222:20:222:30 | access to array element | LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | -| LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | LocalDataFlow.cs:227:15:227:20 | access to local variable sink25 | -| LocalDataFlow.cs:226:22:226:27 | access to local variable sink20 | LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | -| LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | -| LocalDataFlow.cs:226:32:226:36 | false | LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | -| LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | LocalDataFlow.cs:231:15:231:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:230:20:230:27 | access to local variable nonSink7 | LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | -| LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | -| LocalDataFlow.cs:230:32:230:36 | false | LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | -| LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | -| LocalDataFlow.cs:234:22:234:43 | object creation of type Uri | LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | -| LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | LocalDataFlow.cs:234:22:234:43 | object creation of type Uri | -| LocalDataFlow.cs:235:15:235:20 | [post] access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | LocalDataFlow.cs:237:15:237:20 | access to local variable sink27 | -| LocalDataFlow.cs:236:22:236:27 | [post] access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | LocalDataFlow.cs:236:22:236:38 | call to method ToString | -| LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:38 | call to method ToString | LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | -| LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | LocalDataFlow.cs:239:15:239:20 | access to local variable sink28 | -| LocalDataFlow.cs:238:22:238:27 | [post] access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | LocalDataFlow.cs:238:22:238:40 | access to property PathAndQuery | -| LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:40 | access to property PathAndQuery | LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | -| LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | LocalDataFlow.cs:241:15:241:20 | access to local variable sink29 | -| LocalDataFlow.cs:240:22:240:27 | [post] access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | LocalDataFlow.cs:240:22:240:33 | access to property Query | -| LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:33 | access to property Query | LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | -| LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | -| LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | LocalDataFlow.cs:242:22:242:42 | access to property OriginalString | -| LocalDataFlow.cs:242:22:242:42 | access to property OriginalString | LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | -| LocalDataFlow.cs:243:15:243:20 | [post] access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | -| LocalDataFlow.cs:246:24:246:47 | object creation of type Uri | LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | -| LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | LocalDataFlow.cs:246:24:246:47 | object creation of type Uri | -| LocalDataFlow.cs:247:15:247:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | LocalDataFlow.cs:249:15:249:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:248:20:248:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:38 | call to method ToString | -| LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:38 | call to method ToString | LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | LocalDataFlow.cs:251:15:251:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:250:20:250:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:40 | access to property PathAndQuery | -| LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:40 | access to property PathAndQuery | LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | LocalDataFlow.cs:253:15:253:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:252:20:252:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:33 | access to property Query | -| LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:33 | access to property Query | LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | -| LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:42 | access to property OriginalString | -| LocalDataFlow.cs:254:20:254:42 | access to property OriginalString | LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | -| LocalDataFlow.cs:255:15:255:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | -| LocalDataFlow.cs:258:22:258:55 | object creation of type StringReader | LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | -| LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | LocalDataFlow.cs:258:22:258:55 | object creation of type StringReader | -| LocalDataFlow.cs:259:15:259:20 | [post] access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | -| LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | LocalDataFlow.cs:260:22:260:39 | call to method ReadToEnd | -| LocalDataFlow.cs:260:22:260:39 | call to method ReadToEnd | LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | -| LocalDataFlow.cs:261:15:261:20 | [post] access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | -| LocalDataFlow.cs:264:24:264:59 | object creation of type StringReader | LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | -| LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | LocalDataFlow.cs:264:24:264:59 | object creation of type StringReader | -| LocalDataFlow.cs:265:15:265:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:39 | call to method ReadToEnd | -| LocalDataFlow.cs:266:20:266:39 | call to method ReadToEnd | LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:267:15:267:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | -| LocalDataFlow.cs:270:22:270:127 | (...) ... | LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | -| LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | LocalDataFlow.cs:270:30:270:48 | call to method Substring | -| LocalDataFlow.cs:270:30:270:48 | call to method Substring | LocalDataFlow.cs:270:30:270:67 | call to method ToLowerInvariant | -| LocalDataFlow.cs:270:30:270:67 | call to method ToLowerInvariant | LocalDataFlow.cs:270:30:270:77 | call to method ToUpper | -| LocalDataFlow.cs:270:30:270:77 | call to method ToUpper | LocalDataFlow.cs:270:30:270:87 | call to method Trim | -| LocalDataFlow.cs:270:30:270:87 | call to method Trim | LocalDataFlow.cs:270:30:270:105 | call to method Replace | -| LocalDataFlow.cs:270:30:270:105 | call to method Replace | LocalDataFlow.cs:270:30:270:119 | call to method Insert | -| LocalDataFlow.cs:270:30:270:119 | call to method Insert | LocalDataFlow.cs:270:30:270:127 | call to method Clone | -| LocalDataFlow.cs:270:30:270:127 | call to method Clone | LocalDataFlow.cs:270:22:270:127 | (...) ... | -| LocalDataFlow.cs:270:102:270:104 | "b" | LocalDataFlow.cs:270:30:270:105 | call to method Replace | -| LocalDataFlow.cs:270:117:270:118 | "" | LocalDataFlow.cs:270:30:270:119 | call to method Insert | -| LocalDataFlow.cs:271:15:271:20 | [post] access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | LocalDataFlow.cs:273:15:273:20 | access to local variable sink48 | -| LocalDataFlow.cs:272:22:272:27 | [post] access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | LocalDataFlow.cs:272:22:272:39 | call to method Normalize | -| LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:39 | call to method Normalize | LocalDataFlow.cs:272:22:272:52 | call to method Remove | -| LocalDataFlow.cs:272:22:272:52 | call to method Remove | LocalDataFlow.cs:272:22:272:63 | call to method Split | -| LocalDataFlow.cs:272:22:272:63 | call to method Split | LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | -| LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:276:20:276:127 | (...) ... | LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | -| LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:48 | call to method Substring | -| LocalDataFlow.cs:276:28:276:48 | call to method Substring | LocalDataFlow.cs:276:28:276:67 | call to method ToLowerInvariant | -| LocalDataFlow.cs:276:28:276:67 | call to method ToLowerInvariant | LocalDataFlow.cs:276:28:276:77 | call to method ToUpper | -| LocalDataFlow.cs:276:28:276:77 | call to method ToUpper | LocalDataFlow.cs:276:28:276:87 | call to method Trim | -| LocalDataFlow.cs:276:28:276:87 | call to method Trim | LocalDataFlow.cs:276:28:276:105 | call to method Replace | -| LocalDataFlow.cs:276:28:276:105 | call to method Replace | LocalDataFlow.cs:276:28:276:119 | call to method Insert | -| LocalDataFlow.cs:276:28:276:119 | call to method Insert | LocalDataFlow.cs:276:28:276:127 | call to method Clone | -| LocalDataFlow.cs:276:28:276:127 | call to method Clone | LocalDataFlow.cs:276:20:276:127 | (...) ... | -| LocalDataFlow.cs:276:102:276:104 | "b" | LocalDataFlow.cs:276:28:276:105 | call to method Replace | -| LocalDataFlow.cs:276:117:276:118 | "" | LocalDataFlow.cs:276:28:276:119 | call to method Insert | -| LocalDataFlow.cs:277:15:277:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | LocalDataFlow.cs:279:15:279:23 | access to local variable nonSink15 | -| LocalDataFlow.cs:278:25:278:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:44 | call to method Normalize | -| LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:44 | call to method Normalize | LocalDataFlow.cs:278:25:278:57 | call to method Remove | -| LocalDataFlow.cs:278:25:278:57 | call to method Remove | LocalDataFlow.cs:278:25:278:68 | call to method Split | -| LocalDataFlow.cs:278:25:278:68 | call to method Split | LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | -| LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | -| LocalDataFlow.cs:282:22:282:46 | object creation of type StringBuilder | LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | -| LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | LocalDataFlow.cs:282:22:282:46 | object creation of type StringBuilder | -| LocalDataFlow.cs:283:15:283:20 | [post] access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | -| LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | LocalDataFlow.cs:284:22:284:38 | call to method ToString | -| LocalDataFlow.cs:284:22:284:38 | call to method ToString | LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | -| LocalDataFlow.cs:285:15:285:20 | [post] access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | -| LocalDataFlow.cs:286:22:286:42 | object creation of type StringBuilder | LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | -| LocalDataFlow.cs:286:40:286:41 | "" | LocalDataFlow.cs:286:22:286:42 | object creation of type StringBuilder | -| LocalDataFlow.cs:287:9:287:14 | [post] access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | -| LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:291:25:291:51 | object creation of type StringBuilder | LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | -| LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | LocalDataFlow.cs:291:25:291:51 | object creation of type StringBuilder | -| LocalDataFlow.cs:292:15:292:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:293:20:293:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:39 | call to method ToString | -| LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:39 | call to method ToString | LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:294:15:294:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:295:9:295:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | -| LocalDataFlow.cs:299:39:299:51 | [output] delegate creation of type Func | LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | -| LocalDataFlow.cs:299:39:299:51 | this access | LocalDataFlow.cs:309:42:309:57 | this access | -| LocalDataFlow.cs:300:15:300:20 | [post] access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:33 | access to property Value | -| LocalDataFlow.cs:301:22:301:33 | access to property Value | LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | -| LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | -| LocalDataFlow.cs:303:39:303:58 | [output] (...) => ... | LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | -| LocalDataFlow.cs:304:15:304:20 | [post] access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:33 | access to property Value | -| LocalDataFlow.cs:305:22:305:33 | access to property Value | LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | -| LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | -| LocalDataFlow.cs:309:42:309:57 | [output] delegate creation of type Func | LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | -| LocalDataFlow.cs:310:15:310:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | LocalDataFlow.cs:312:15:312:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:34 | access to property Value | -| LocalDataFlow.cs:311:20:311:34 | access to property Value | LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | -| LocalDataFlow.cs:313:38:313:45 | [output] (...) => ... | LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | -| LocalDataFlow.cs:314:15:314:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:34 | access to property Value | -| LocalDataFlow.cs:315:20:315:34 | access to property Value | LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:316:15:316:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | -| LocalDataFlow.cs:319:21:319:49 | object creation of type Dictionary | LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | -| LocalDataFlow.cs:320:9:320:13 | [post] access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:22:320:26 | [post] access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | -| LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:321:15:321:19 | [post] access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | -| LocalDataFlow.cs:322:22:322:26 | [post] access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | LocalDataFlow.cs:322:22:322:33 | access to property Values | -| LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:33 | access to property Values | LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | -| LocalDataFlow.cs:323:15:323:20 | [post] access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | LocalDataFlow.cs:325:15:325:20 | access to local variable sink13 | -| LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | LocalDataFlow.cs:324:22:324:37 | call to method Reverse | -| LocalDataFlow.cs:324:22:324:37 | call to method Reverse | LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | -| LocalDataFlow.cs:328:9:328:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:22:329:26 | [post] access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:329:29:329:30 | "" | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:330:15:330:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | -| LocalDataFlow.cs:331:24:331:31 | [post] access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:38 | access to property Values | -| LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:38 | access to property Values | LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | -| LocalDataFlow.cs:332:15:332:22 | [post] access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | LocalDataFlow.cs:334:15:334:22 | access to local variable nonSink6 | -| LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:41 | call to method Reverse | -| LocalDataFlow.cs:333:24:333:41 | call to method Reverse | LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | -| LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:337:13:337:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:340:22:340:46 | access to property AList | -| LocalDataFlow.cs:337:35:337:52 | object creation of type DataContract | LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | -| LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | LocalDataFlow.cs:339:15:339:20 | access to local variable sink53 | -| LocalDataFlow.cs:338:22:338:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | LocalDataFlow.cs:338:22:338:48 | access to property AString | -| LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:48 | access to property AString | LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | -| LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | LocalDataFlow.cs:341:15:341:20 | access to local variable sink54 | -| LocalDataFlow.cs:340:22:340:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:46 | access to property AList | -| LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:46 | [post] access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:46 | access to property AList | LocalDataFlow.cs:340:22:340:49 | access to indexer | -| LocalDataFlow.cs:340:22:340:46 | access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:49 | access to indexer | LocalDataFlow.cs:340:22:340:57 | access to property AString | -| LocalDataFlow.cs:340:22:340:57 | access to property AString | LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | -| LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:345:20:345:41 | access to local variable nonTaintedDataContract | -| LocalDataFlow.cs:344:38:344:55 | object creation of type DataContract | LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | -| LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | LocalDataFlow.cs:346:15:346:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:345:20:345:41 | access to local variable nonTaintedDataContract | LocalDataFlow.cs:345:20:345:49 | access to property AString | -| LocalDataFlow.cs:345:20:345:49 | access to property AString | LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | -| LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | LocalDataFlow.cs:348:15:348:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:347:20:347:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:44 | access to property AnInt | LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | -| LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | LocalDataFlow.cs:350:15:350:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:349:20:349:44 | access to property AList | LocalDataFlow.cs:349:20:349:47 | access to indexer | -| LocalDataFlow.cs:349:20:349:53 | access to property AnInt | LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | -| LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:354:22:354:35 | access to local variable taintedTextBox | -| LocalDataFlow.cs:353:34:353:37 | null | LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | -| LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | LocalDataFlow.cs:355:15:355:20 | access to local variable sink60 | -| LocalDataFlow.cs:354:22:354:35 | access to local variable taintedTextBox | LocalDataFlow.cs:354:22:354:40 | access to property Text | -| LocalDataFlow.cs:354:22:354:40 | access to property Text | LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | -| LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:359:20:359:36 | access to local variable nonTaintedTextBox | -| LocalDataFlow.cs:358:37:358:40 | null | LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | -| LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | LocalDataFlow.cs:360:15:360:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:359:20:359:36 | access to local variable nonTaintedTextBox | LocalDataFlow.cs:359:20:359:41 | access to property Text | -| LocalDataFlow.cs:359:20:359:41 | access to property Text | LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:363:22:363:27 | SSA def(sink61) | LocalDataFlow.cs:364:19:364:24 | access to local variable sink61 | -| LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | LocalDataFlow.cs:363:22:363:27 | SSA def(sink61) | -| LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | LocalDataFlow.cs:365:30:365:35 | access to local variable sink10 | -| LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | -| LocalDataFlow.cs:365:30:365:35 | access to local variable sink10 | LocalDataFlow.cs:365:30:365:51 | call to method GetEnumerator | -| LocalDataFlow.cs:365:30:365:51 | call to method GetEnumerator | LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | -| LocalDataFlow.cs:366:15:366:20 | [post] access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | LocalDataFlow.cs:368:15:368:20 | access to local variable sink63 | -| LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:35 | access to property Current | -| LocalDataFlow.cs:367:22:367:35 | access to property Current | LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | -| LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | -| LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | LocalDataFlow.cs:369:57:369:77 | call to method GetEnumerator | -| LocalDataFlow.cs:369:57:369:77 | (...) ... | LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | -| LocalDataFlow.cs:369:57:369:77 | call to method GetEnumerator | LocalDataFlow.cs:369:57:369:77 | (...) ... | -| LocalDataFlow.cs:370:15:370:20 | [post] access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | -| LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:35 | access to property Current | -| LocalDataFlow.cs:371:22:371:35 | access to property Current | LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | -| LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | -| LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | LocalDataFlow.cs:374:15:374:20 | access to local variable sink66 | -| LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:33 | access to property Value | -| LocalDataFlow.cs:373:22:373:33 | access to property Value | LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | -| LocalDataFlow.cs:377:22:377:30 | SSA def(nonSink17) | LocalDataFlow.cs:378:19:378:27 | access to local variable nonSink17 | -| LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | LocalDataFlow.cs:377:22:377:30 | SSA def(nonSink17) | -| LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | LocalDataFlow.cs:379:33:379:40 | access to local variable nonSink4 | -| LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | -| LocalDataFlow.cs:379:33:379:40 | access to local variable nonSink4 | LocalDataFlow.cs:379:33:379:56 | call to method GetEnumerator | -| LocalDataFlow.cs:379:33:379:56 | call to method GetEnumerator | LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | -| LocalDataFlow.cs:380:15:380:23 | [post] access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | LocalDataFlow.cs:382:15:382:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:36 | access to property Current | -| LocalDataFlow.cs:381:20:381:36 | access to property Current | LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | -| LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | -| LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:86 | call to method GetEnumerator | -| LocalDataFlow.cs:383:63:383:86 | (...) ... | LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | -| LocalDataFlow.cs:383:63:383:86 | call to method GetEnumerator | LocalDataFlow.cs:383:63:383:86 | (...) ... | -| LocalDataFlow.cs:384:15:384:23 | [post] access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | -| LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:41 | access to property Current | -| LocalDataFlow.cs:385:25:385:41 | access to property Current | LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | -| LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | -| LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | LocalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:34 | access to property Value | -| LocalDataFlow.cs:387:20:387:34 | access to property Value | LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:391:22:391:51 | call to method Run | LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | -| LocalDataFlow.cs:391:31:391:50 | [output] (...) => ... | LocalDataFlow.cs:391:22:391:51 | call to method Run | -| LocalDataFlow.cs:392:15:392:20 | [post] access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:393:22:393:33 | await ... | LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | -| LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | LocalDataFlow.cs:393:22:393:33 | await ... | -| LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | -| LocalDataFlow.cs:397:25:397:42 | call to method Run | LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | -| LocalDataFlow.cs:397:34:397:41 | [output] (...) => ... | LocalDataFlow.cs:397:25:397:42 | call to method Run | -| LocalDataFlow.cs:398:15:398:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:399:20:399:34 | await ... | LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | LocalDataFlow.cs:399:20:399:34 | await ... | -| LocalDataFlow.cs:400:15:400:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | LocalDataFlow.cs:404:15:404:20 | access to local variable sink69 | -| LocalDataFlow.cs:403:22:403:36 | $"..." | LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | -| LocalDataFlow.cs:403:24:403:28 | "test " | LocalDataFlow.cs:403:22:403:36 | $"..." | -| LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | LocalDataFlow.cs:403:22:403:36 | $"..." | -| LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:407:20:407:37 | $"..." | LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | -| LocalDataFlow.cs:407:22:407:26 | "test " | LocalDataFlow.cs:407:20:407:37 | $"..." | -| LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | LocalDataFlow.cs:407:20:407:37 | $"..." | -| LocalDataFlow.cs:408:15:408:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:411:22:411:34 | ... = ... | LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | ... = ... | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | -| LocalDataFlow.cs:412:15:412:20 | [post] access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:415:20:415:38 | ... = ... | LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | LocalDataFlow.cs:415:20:415:38 | ... = ... | -| LocalDataFlow.cs:416:15:416:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | -| LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | -| LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | LocalDataFlow.cs:424:19:424:27 | access to local variable nonSink16 | -| LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | -| LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | LocalDataFlow.cs:438:23:438:31 | access to local variable nonSink17 | -| LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:443:22:443:38 | ... ?? ... | LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:444:22:444:38 | ... ?? ... | LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | -| LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:464:28:464:30 | this | LocalDataFlow.cs:464:41:464:45 | this access | -| LocalDataFlow.cs:464:50:464:52 | this | LocalDataFlow.cs:464:56:464:60 | this access | -| LocalDataFlow.cs:464:50:464:52 | value | LocalDataFlow.cs:464:50:464:52 | value | -| LocalDataFlow.cs:464:50:464:52 | value | LocalDataFlow.cs:464:64:464:68 | access to parameter value | -| LocalDataFlow.cs:470:41:470:47 | tainted | LocalDataFlow.cs:470:41:470:47 | tainted | -| LocalDataFlow.cs:470:41:470:47 | tainted | LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | -| LocalDataFlow.cs:475:44:475:53 | nonTainted | LocalDataFlow.cs:475:44:475:53 | nonTainted | -| LocalDataFlow.cs:475:44:475:53 | nonTainted | LocalDataFlow.cs:477:15:477:24 | access to parameter nonTainted | -| LocalDataFlow.cs:480:44:480:44 | x | LocalDataFlow.cs:480:44:480:44 | x | -| LocalDataFlow.cs:480:44:480:44 | x | LocalDataFlow.cs:483:21:483:21 | access to parameter x | -| LocalDataFlow.cs:480:67:480:68 | os | LocalDataFlow.cs:480:67:480:68 | os | -| LocalDataFlow.cs:480:67:480:68 | os | LocalDataFlow.cs:486:32:486:33 | access to parameter os | -| LocalDataFlow.cs:483:21:483:21 | access to parameter x | LocalDataFlow.cs:483:16:483:21 | ... = ... | -| LocalDataFlow.cs:486:32:486:33 | access to parameter os | LocalDataFlow.cs:486:26:486:33 | ... = ... | -| LocalDataFlow.cs:491:41:491:44 | args | LocalDataFlow.cs:491:41:491:44 | args | -| LocalDataFlow.cs:491:41:491:44 | args | LocalDataFlow.cs:493:29:493:32 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | [post] access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | access to parameter args | LocalDataFlow.cs:493:29:493:32 | call to operator implicit conversion | -| LocalDataFlow.cs:493:29:493:32 | access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | +| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | +| LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | LocalDataFlow.cs:69:21:69:32 | ... + ... | +| LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | +| LocalDataFlow.cs:69:21:69:32 | ... + ... | LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | +| LocalDataFlow.cs:69:29:69:32 | "ok" | LocalDataFlow.cs:69:21:69:32 | ... + ... | +| LocalDataFlow.cs:70:15:70:19 | [post] access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:36 | ... + ... | +| LocalDataFlow.cs:73:20:73:36 | ... + ... | LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:73:31:73:36 | "test" | LocalDataFlow.cs:73:20:73:36 | ... + ... | +| LocalDataFlow.cs:74:15:74:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | +| LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | +| LocalDataFlow.cs:78:15:78:19 | [post] access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | LocalDataFlow.cs:82:15:82:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): false] access to parameter b | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): true] access to parameter b | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | +| LocalDataFlow.cs:85:25:85:27 | [b (line 49): true] "a" | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:24:89:28 | "abc" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | +| LocalDataFlow.cs:89:32:89:36 | "def" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | +| LocalDataFlow.cs:90:15:90:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | +| LocalDataFlow.cs:93:21:93:33 | (...) ... | LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | +| LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | LocalDataFlow.cs:93:21:93:33 | (...) ... | +| LocalDataFlow.cs:94:15:94:19 | [post] access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | LocalDataFlow.cs:98:15:98:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:97:24:97:39 | (...) ... | LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:97:24:97:39 | (...) ... | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:35 | ... as ... | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | +| LocalDataFlow.cs:101:21:101:35 | ... as ... | LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | +| LocalDataFlow.cs:102:15:102:19 | [post] access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:37 | ... as ... | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:105:20:105:37 | ... as ... | LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | +| LocalDataFlow.cs:106:15:106:22 | [post] access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | +| LocalDataFlow.cs:109:22:109:39 | call to method Parse | LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | +| LocalDataFlow.cs:109:34:109:38 | [post] access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:109:22:109:39 | call to method Parse | +| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | LocalDataFlow.cs:161:22:161:27 | access to local variable sink15 | +| LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | LocalDataFlow.cs:113:15:113:20 | access to local variable sink16 | +| LocalDataFlow.cs:112:22:112:56 | call to method TryParse | LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | +| LocalDataFlow.cs:112:37:112:41 | [post] access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:112:22:112:56 | call to method TryParse | +| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | LocalDataFlow.cs:115:15:115:20 | access to local variable sink17 | +| LocalDataFlow.cs:114:22:114:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:49 | call to method Replace | +| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:49 | call to method Replace | LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | +| LocalDataFlow.cs:114:44:114:48 | [post] access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:114:22:114:49 | call to method Replace | +| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | +| LocalDataFlow.cs:116:22:116:51 | call to method Format | LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | +| LocalDataFlow.cs:116:36:116:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:116:22:116:51 | call to method Format | +| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:46:116:50 | [post] access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:116:22:116:51 | call to method Format | +| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:117:15:117:20 | [post] access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | LocalDataFlow.cs:119:15:119:20 | access to local variable sink19 | +| LocalDataFlow.cs:118:22:118:52 | call to method Format | LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | +| LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | LocalDataFlow.cs:118:22:118:52 | call to method Format | +| LocalDataFlow.cs:118:44:118:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:118:22:118:52 | call to method Format | +| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink45 | +| LocalDataFlow.cs:120:22:120:38 | call to method Parse | LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | +| LocalDataFlow.cs:120:33:120:37 | [post] access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:120:22:120:38 | call to method Parse | +| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | +| LocalDataFlow.cs:123:22:123:56 | call to method TryParse | LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | +| LocalDataFlow.cs:123:36:123:40 | [post] access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:123:22:123:56 | call to method TryParse | +| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | +| LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | +| LocalDataFlow.cs:125:22:125:43 | call to method ToByte | LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | +| LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | LocalDataFlow.cs:125:22:125:43 | call to method ToByte | +| LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | +| LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | +| LocalDataFlow.cs:127:22:127:46 | call to method Concat | LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | +| LocalDataFlow.cs:127:36:127:37 | "" | LocalDataFlow.cs:127:22:127:46 | call to method Concat | +| LocalDataFlow.cs:127:40:127:45 | (...) ... | LocalDataFlow.cs:127:22:127:46 | call to method Concat | +| LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | (...) ... | +| LocalDataFlow.cs:128:15:128:20 | [post] access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | +| LocalDataFlow.cs:129:22:129:40 | call to method Copy | LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | +| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | call to method Copy | +| LocalDataFlow.cs:130:15:130:20 | [post] access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | +| LocalDataFlow.cs:131:22:131:54 | call to method Join | LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | +| LocalDataFlow.cs:131:34:131:37 | ", " | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:131:40:131:41 | "" | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:131:52:131:53 | "" | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:132:15:132:20 | [post] access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | LocalDataFlow.cs:134:15:134:20 | access to local variable sink52 | +| LocalDataFlow.cs:133:22:133:23 | "" | LocalDataFlow.cs:133:22:133:41 | call to method Insert | +| LocalDataFlow.cs:133:22:133:41 | call to method Insert | LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | +| LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | LocalDataFlow.cs:133:22:133:41 | call to method Insert | +| LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | LocalDataFlow.cs:138:15:138:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:137:20:137:40 | call to method Parse | LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | +| LocalDataFlow.cs:137:32:137:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:137:20:137:40 | call to method Parse | +| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | LocalDataFlow.cs:140:15:140:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:139:24:139:61 | call to method TryParse | LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | +| LocalDataFlow.cs:139:39:139:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:139:24:139:61 | call to method TryParse | +| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | call to method Replace | +| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:50 | call to method Replace | LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | +| LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | call to method Replace | +| LocalDataFlow.cs:142:15:142:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:20:143:52 | call to method Format | LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | +| LocalDataFlow.cs:143:34:143:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | call to method Format | +| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | call to method Format | +| LocalDataFlow.cs:144:15:144:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | LocalDataFlow.cs:146:15:146:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:145:20:145:39 | call to method Parse | LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | +| LocalDataFlow.cs:145:31:145:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:145:20:145:39 | call to method Parse | +| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:147:20:147:57 | call to method TryParse | LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | +| LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | LocalDataFlow.cs:147:20:147:57 | call to method TryParse | +| LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | +| LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | LocalDataFlow.cs:150:15:150:23 | access to local variable nonSink14 | +| LocalDataFlow.cs:149:25:149:48 | call to method ToByte | LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | +| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:149:25:149:48 | call to method ToByte | +| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | +| LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:151:20:151:46 | call to method Concat | LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | +| LocalDataFlow.cs:151:34:151:35 | "" | LocalDataFlow.cs:151:20:151:46 | call to method Concat | +| LocalDataFlow.cs:151:38:151:45 | (...) ... | LocalDataFlow.cs:151:20:151:46 | call to method Concat | +| LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | (...) ... | +| LocalDataFlow.cs:152:15:152:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:20:153:40 | call to method Copy | LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | call to method Copy | +| LocalDataFlow.cs:154:15:154:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:20:155:54 | call to method Join | LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | +| LocalDataFlow.cs:155:32:155:35 | ", " | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:155:38:155:39 | "" | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:155:52:155:53 | "" | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:156:15:156:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:20:157:21 | "" | LocalDataFlow.cs:157:20:157:41 | call to method Insert | +| LocalDataFlow.cs:157:20:157:41 | call to method Insert | LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | LocalDataFlow.cs:157:20:157:41 | call to method Insert | +| LocalDataFlow.cs:158:15:158:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | +| LocalDataFlow.cs:161:22:161:27 | access to local variable sink15 | LocalDataFlow.cs:161:22:161:32 | ... > ... | +| LocalDataFlow.cs:161:22:161:32 | ... > ... | LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | +| LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | LocalDataFlow.cs:175:22:175:27 | access to local variable sink20 | +| LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | LocalDataFlow.cs:164:15:164:20 | access to local variable sink21 | +| LocalDataFlow.cs:163:22:163:26 | [post] access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | LocalDataFlow.cs:163:22:163:40 | call to method Equals | +| LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:40 | call to method Equals | LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | +| LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | LocalDataFlow.cs:166:15:166:20 | access to local variable sink22 | +| LocalDataFlow.cs:165:22:165:26 | [post] access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | LocalDataFlow.cs:165:22:165:45 | call to method Equals | +| LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:45 | call to method Equals | LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | +| LocalDataFlow.cs:165:43:165:44 | 41 | LocalDataFlow.cs:165:35:165:44 | (...) ... | +| LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | LocalDataFlow.cs:170:15:170:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:169:20:169:24 | [post] access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:38 | call to method Equals | LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | +| LocalDataFlow.cs:169:33:169:37 | [post] access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:171:20:171:41 | call to method Equals | LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | +| LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | LocalDataFlow.cs:179:20:179:27 | access to local variable nonSink7 | +| LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | LocalDataFlow.cs:176:15:176:20 | access to local variable sink25 | +| LocalDataFlow.cs:175:22:175:27 | access to local variable sink20 | LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | +| LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | +| LocalDataFlow.cs:175:32:175:36 | false | LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | +| LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | LocalDataFlow.cs:180:15:180:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:179:20:179:27 | access to local variable nonSink7 | LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | +| LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | +| LocalDataFlow.cs:179:32:179:36 | false | LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | +| LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | +| LocalDataFlow.cs:183:22:183:42 | object creation of type Uri | LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | +| LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | LocalDataFlow.cs:183:22:183:42 | object creation of type Uri | +| LocalDataFlow.cs:184:15:184:20 | [post] access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | LocalDataFlow.cs:186:15:186:20 | access to local variable sink27 | +| LocalDataFlow.cs:185:22:185:27 | [post] access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:38 | call to method ToString | +| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:38 | call to method ToString | LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | +| LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | LocalDataFlow.cs:188:15:188:20 | access to local variable sink28 | +| LocalDataFlow.cs:187:22:187:27 | [post] access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery | +| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery | LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | +| LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | LocalDataFlow.cs:190:15:190:20 | access to local variable sink29 | +| LocalDataFlow.cs:189:22:189:27 | [post] access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:33 | access to property Query | +| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:33 | access to property Query | LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | +| LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | +| LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:42 | access to property OriginalString | +| LocalDataFlow.cs:191:22:191:42 | access to property OriginalString | LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | +| LocalDataFlow.cs:192:15:192:20 | [post] access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | +| LocalDataFlow.cs:195:24:195:47 | object creation of type Uri | LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | +| LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | LocalDataFlow.cs:195:24:195:47 | object creation of type Uri | +| LocalDataFlow.cs:196:15:196:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | LocalDataFlow.cs:198:15:198:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:197:20:197:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:38 | call to method ToString | +| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:38 | call to method ToString | LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | LocalDataFlow.cs:200:15:200:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:199:20:199:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery | +| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery | LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | LocalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:201:20:201:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:33 | access to property Query | +| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:33 | access to property Query | LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | +| LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:42 | access to property OriginalString | +| LocalDataFlow.cs:203:20:203:42 | access to property OriginalString | LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | +| LocalDataFlow.cs:204:15:204:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | +| LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader | LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | +| LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader | +| LocalDataFlow.cs:208:15:208:20 | [post] access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | +| LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd | +| LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd | LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | +| LocalDataFlow.cs:210:15:210:20 | [post] access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | +| LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader | LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | +| LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader | +| LocalDataFlow.cs:214:15:214:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd | +| LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd | LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:216:15:216:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | +| LocalDataFlow.cs:219:22:219:127 | (...) ... | LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | +| LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:48 | call to method Substring | +| LocalDataFlow.cs:219:30:219:48 | call to method Substring | LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant | +| LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant | LocalDataFlow.cs:219:30:219:77 | call to method ToUpper | +| LocalDataFlow.cs:219:30:219:77 | call to method ToUpper | LocalDataFlow.cs:219:30:219:87 | call to method Trim | +| LocalDataFlow.cs:219:30:219:87 | call to method Trim | LocalDataFlow.cs:219:30:219:105 | call to method Replace | +| LocalDataFlow.cs:219:30:219:105 | call to method Replace | LocalDataFlow.cs:219:30:219:119 | call to method Insert | +| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | call to method Clone | +| LocalDataFlow.cs:219:30:219:127 | call to method Clone | LocalDataFlow.cs:219:22:219:127 | (...) ... | +| LocalDataFlow.cs:219:102:219:104 | "b" | LocalDataFlow.cs:219:30:219:105 | call to method Replace | +| LocalDataFlow.cs:219:117:219:118 | "" | LocalDataFlow.cs:219:30:219:119 | call to method Insert | +| LocalDataFlow.cs:220:15:220:20 | [post] access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | LocalDataFlow.cs:222:15:222:20 | access to local variable sink48 | +| LocalDataFlow.cs:221:22:221:27 | [post] access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:39 | call to method Normalize | +| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:39 | call to method Normalize | LocalDataFlow.cs:221:22:221:52 | call to method Remove | +| LocalDataFlow.cs:221:22:221:52 | call to method Remove | LocalDataFlow.cs:221:22:221:63 | call to method Split | +| LocalDataFlow.cs:221:22:221:63 | call to method Split | LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | +| LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:225:20:225:127 | (...) ... | LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | +| LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:48 | call to method Substring | +| LocalDataFlow.cs:225:28:225:48 | call to method Substring | LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant | +| LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant | LocalDataFlow.cs:225:28:225:77 | call to method ToUpper | +| LocalDataFlow.cs:225:28:225:77 | call to method ToUpper | LocalDataFlow.cs:225:28:225:87 | call to method Trim | +| LocalDataFlow.cs:225:28:225:87 | call to method Trim | LocalDataFlow.cs:225:28:225:105 | call to method Replace | +| LocalDataFlow.cs:225:28:225:105 | call to method Replace | LocalDataFlow.cs:225:28:225:119 | call to method Insert | +| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | call to method Clone | +| LocalDataFlow.cs:225:28:225:127 | call to method Clone | LocalDataFlow.cs:225:20:225:127 | (...) ... | +| LocalDataFlow.cs:225:102:225:104 | "b" | LocalDataFlow.cs:225:28:225:105 | call to method Replace | +| LocalDataFlow.cs:225:117:225:118 | "" | LocalDataFlow.cs:225:28:225:119 | call to method Insert | +| LocalDataFlow.cs:226:15:226:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | LocalDataFlow.cs:228:15:228:23 | access to local variable nonSink15 | +| LocalDataFlow.cs:227:25:227:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:44 | call to method Normalize | +| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:44 | call to method Normalize | LocalDataFlow.cs:227:25:227:57 | call to method Remove | +| LocalDataFlow.cs:227:25:227:57 | call to method Remove | LocalDataFlow.cs:227:25:227:68 | call to method Split | +| LocalDataFlow.cs:227:25:227:68 | call to method Split | LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | +| LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | +| LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder | LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | +| LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder | +| LocalDataFlow.cs:232:15:232:20 | [post] access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | +| LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:38 | call to method ToString | +| LocalDataFlow.cs:233:22:233:38 | call to method ToString | LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | +| LocalDataFlow.cs:234:15:234:20 | [post] access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | +| LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder | LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | +| LocalDataFlow.cs:235:40:235:41 | "" | LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder | +| LocalDataFlow.cs:236:9:236:14 | [post] access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | +| LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder | LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | +| LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder | +| LocalDataFlow.cs:241:15:241:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:242:20:242:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:39 | call to method ToString | +| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:39 | call to method ToString | LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:243:15:243:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:244:9:244:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:248:13:248:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:251:22:251:46 | access to property AList | +| LocalDataFlow.cs:248:35:248:52 | object creation of type DataContract | LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | +| LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | LocalDataFlow.cs:250:15:250:20 | access to local variable sink53 | +| LocalDataFlow.cs:249:22:249:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:249:22:249:48 | access to property AString | +| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:48 | access to property AString | LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | +| LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | LocalDataFlow.cs:252:15:252:20 | access to local variable sink54 | +| LocalDataFlow.cs:251:22:251:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:46 | access to property AList | +| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:46 | [post] access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:251:22:251:49 | access to indexer | +| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:49 | access to indexer | LocalDataFlow.cs:251:22:251:57 | access to property AString | +| LocalDataFlow.cs:251:22:251:57 | access to property AString | LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | +| LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | +| LocalDataFlow.cs:255:38:255:55 | object creation of type DataContract | LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | +| LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | LocalDataFlow.cs:257:15:257:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | LocalDataFlow.cs:256:20:256:49 | access to property AString | +| LocalDataFlow.cs:256:20:256:49 | access to property AString | LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | +| LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | LocalDataFlow.cs:259:15:259:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:258:20:258:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:44 | access to property AnInt | LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | +| LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | LocalDataFlow.cs:261:15:261:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:260:20:260:44 | access to property AList | LocalDataFlow.cs:260:20:260:47 | access to indexer | +| LocalDataFlow.cs:260:20:260:53 | access to property AnInt | LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | +| LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | +| LocalDataFlow.cs:264:34:264:37 | null | LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | +| LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | LocalDataFlow.cs:266:15:266:20 | access to local variable sink60 | +| LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | LocalDataFlow.cs:265:22:265:40 | access to property Text | +| LocalDataFlow.cs:265:22:265:40 | access to property Text | LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | +| LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | +| LocalDataFlow.cs:269:37:269:40 | null | LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | +| LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | LocalDataFlow.cs:271:15:271:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | LocalDataFlow.cs:270:20:270:41 | access to property Text | +| LocalDataFlow.cs:270:20:270:41 | access to property Text | LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:274:22:274:51 | call to method Run | LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | +| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | call to method Run | +| LocalDataFlow.cs:275:15:275:20 | [post] access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:276:22:276:33 | await ... | LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | +| LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | LocalDataFlow.cs:276:22:276:33 | await ... | +| LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | +| LocalDataFlow.cs:280:25:280:42 | call to method Run | LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | +| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | call to method Run | +| LocalDataFlow.cs:281:15:281:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:282:20:282:34 | await ... | LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | +| LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | LocalDataFlow.cs:282:20:282:34 | await ... | +| LocalDataFlow.cs:283:15:283:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | LocalDataFlow.cs:287:15:287:20 | access to local variable sink69 | +| LocalDataFlow.cs:286:22:286:36 | $"..." | LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | +| LocalDataFlow.cs:286:24:286:28 | "test " | LocalDataFlow.cs:286:22:286:36 | $"..." | +| LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | LocalDataFlow.cs:286:22:286:36 | $"..." | +| LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:290:20:290:37 | $"..." | LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | +| LocalDataFlow.cs:290:22:290:26 | "test " | LocalDataFlow.cs:290:20:290:37 | $"..." | +| LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | LocalDataFlow.cs:290:20:290:37 | $"..." | +| LocalDataFlow.cs:291:15:291:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:294:22:294:34 | ... = ... | LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | ... = ... | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | +| LocalDataFlow.cs:295:15:295:20 | [post] access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:298:20:298:38 | ... = ... | LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | LocalDataFlow.cs:298:20:298:38 | ... = ... | +| LocalDataFlow.cs:299:15:299:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | +| LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | +| LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | LocalDataFlow.cs:307:19:307:27 | access to local variable nonSink16 | +| LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | +| LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | LocalDataFlow.cs:321:23:321:31 | access to local variable nonSink17 | +| LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:326:22:326:38 | ... ?? ... | LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:327:22:327:38 | ... ?? ... | LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | +| LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:347:28:347:30 | this | LocalDataFlow.cs:347:41:347:45 | this access | +| LocalDataFlow.cs:347:50:347:52 | this | LocalDataFlow.cs:347:56:347:60 | this access | +| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:50:347:52 | value | +| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:64:347:68 | access to parameter value | +| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:353:41:353:47 | tainted | +| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | +| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:358:44:358:53 | nonTainted | +| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:360:15:360:24 | access to parameter nonTainted | +| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:363:44:363:44 | x | +| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:366:21:366:21 | access to parameter x | +| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:363:67:363:68 | os | +| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:369:32:369:33 | access to parameter os | +| LocalDataFlow.cs:366:21:366:21 | access to parameter x | LocalDataFlow.cs:366:16:366:21 | ... = ... | +| LocalDataFlow.cs:369:32:369:33 | access to parameter os | LocalDataFlow.cs:369:26:369:33 | ... = ... | +| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:374:41:374:44 | args | +| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:376:29:376:32 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | [post] access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:376:29:376:32 | call to operator implicit conversion | +| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | | SSA.cs:5:17:5:17 | SSA entry def(this.S) | SSA.cs:67:9:67:14 | access to field S | | SSA.cs:5:17:5:17 | this | SSA.cs:67:9:67:12 | this access | | SSA.cs:5:26:5:32 | tainted | SSA.cs:5:26:5:32 | tainted | From d8dcbe3cbdf69593e81f0fa27da91669a12a6d6c Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 14 Apr 2020 10:20:35 +0200 Subject: [PATCH 412/459] C++: QLDoc for FileClosed, LoopBounds and MemoryFreed --- cpp/ql/src/Critical/FileClosed.qll | 10 ++++++++++ cpp/ql/src/Critical/LoopBounds.qll | 11 +++++++++++ cpp/ql/src/Critical/MemoryFreed.qll | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/cpp/ql/src/Critical/FileClosed.qll b/cpp/ql/src/Critical/FileClosed.qll index 1e782259156..a58af50ba67 100644 --- a/cpp/ql/src/Critical/FileClosed.qll +++ b/cpp/ql/src/Critical/FileClosed.qll @@ -1,5 +1,6 @@ import semmle.code.cpp.pointsto.PointsTo +/** Holds if there exists a call to a function that might close the file specified by `e`. */ predicate closed(Expr e) { fcloseCall(_, e) or exists(ExprCall c | @@ -8,10 +9,19 @@ predicate closed(Expr e) { ) } +/** An expression for which there exists a function call that might close it. */ class ClosedExpr extends PointsToExpr { ClosedExpr() { closed(this) } override predicate interesting() { closed(this) } } +/** + * Holds if `fc` is a call to function that opens a file which might be closed. For example: + * ``` + * FILE* f = fopen("file.txt", "r"); + * ... + * fclose(f); + * ``` + */ predicate fopenCallMayBeClosed(FunctionCall fc) { fopenCall(fc) and anythingPointsTo(fc) } diff --git a/cpp/ql/src/Critical/LoopBounds.qll b/cpp/ql/src/Critical/LoopBounds.qll index f10e62c909f..390655b004e 100644 --- a/cpp/ql/src/Critical/LoopBounds.qll +++ b/cpp/ql/src/Critical/LoopBounds.qll @@ -2,12 +2,23 @@ import cpp +/** An assignment to a variable with the value `0`. For example: + * ``` + * int x; + * x = 0; + * ``` + * but not: + * ``` + * int x = 0; + * ``` + */ class ZeroAssignment extends AssignExpr { ZeroAssignment() { this.getAnOperand() instanceof VariableAccess and this.getAnOperand() instanceof Zero } + /** Gets a variable that is assigned the value `0`. */ Variable assignedVariable() { result.getAnAccess() = this.getAnOperand() } } diff --git a/cpp/ql/src/Critical/MemoryFreed.qll b/cpp/ql/src/Critical/MemoryFreed.qll index 880199e54c9..44557503e43 100644 --- a/cpp/ql/src/Critical/MemoryFreed.qll +++ b/cpp/ql/src/Critical/MemoryFreed.qll @@ -9,10 +9,19 @@ private predicate freed(Expr e) { ) } +/** An expression that might be deallocated. */ class FreedExpr extends PointsToExpr { FreedExpr() { freed(this) } override predicate interesting() { freed(this) } } +/** + * An allocation expression that might be deallocated. For example: + * ``` + * int* p = new int; + * ... + * delete p; + * ``` + */ predicate allocMayBeFreed(AllocationExpr alloc) { anythingPointsTo(alloc) } From e47575ce5b3c676a1137abf8ba44d490f90f86be Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 14 Apr 2020 10:24:08 +0200 Subject: [PATCH 413/459] more precise getChild for matching "../" --- .../javascript/security/dataflow/TaintedPathCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index 66708b4630e..9ec8473fc0a 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -285,7 +285,7 @@ module TaintedPath { exists(RegExpSequence seq | seq = result | seq.getChild(0).getConstantValue() = "." and seq.getChild(1).getConstantValue() = "." and - seq.getAChild().getAMatchedString() = "/" + seq.getChild(2).getAMatchedString() = "/" ) or exists(RegExpGroup group | result = group | group.getChild(0) = getADotDotSlashMatcher()) From dc084628cc2bc612c0f3b92b0bba5acb2b7d22e8 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 9 Apr 2020 09:41:00 +0100 Subject: [PATCH 414/459] JS: Avoid the special name getURL --- javascript/ql/src/semmle/javascript/NPM.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/NPM.qll b/javascript/ql/src/semmle/javascript/NPM.qll index d82200bdf31..1038b04b6c2 100644 --- a/javascript/ql/src/semmle/javascript/NPM.qll +++ b/javascript/ql/src/semmle/javascript/NPM.qll @@ -190,7 +190,7 @@ class BugTrackerInfo extends JSONValue { } /** Gets the bug tracker URL. */ - string getURL() { + string getUrl() { result = this.(JSONObject).getPropStringValue("url") or result = this.(JSONString).getValue() } From 244a304e1d71152b239772b58be145bb44f87ec3 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 9 Apr 2020 09:57:31 +0100 Subject: [PATCH 415/459] JS: Implement getFile() directly instead of via locations --- .../semmle/javascript/dataflow/DataFlow.qll | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index d7bf1e304ea..b3b35142dd6 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -173,7 +173,7 @@ module DataFlow { } /** Gets the file this data flow node comes from. */ - File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) } + File getFile() { none() } // overridden in subclasses /** Gets the start line of this data flow node. */ int getStartLine() { hasLocationInfo(_, result, _, _, _) } @@ -313,6 +313,8 @@ module DataFlow { astNode.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + override File getFile() { result = astNode.getFile() } + override string toString() { result = astNode.toString() } } @@ -337,6 +339,8 @@ module DataFlow { override string toString() { result = ssa.getSourceVariable().getName() } + override File getFile() { result = ssa.getBasicBlock().getFile() } + override ASTNode getAstNode() { none() } } @@ -361,6 +365,8 @@ module DataFlow { override string toString() { result = prop.(ASTNode).toString() } + override File getFile() { result = prop.(ASTNode).getFile() } + override ASTNode getAstNode() { result = prop } } @@ -384,6 +390,8 @@ module DataFlow { override string toString() { result = "..." + rest.toString() } + override File getFile() { result = pattern.getFile() } + override ASTNode getAstNode() { result = rest } } @@ -406,6 +414,8 @@ module DataFlow { override string toString() { result = pattern.toString() } + override File getFile() { result = pattern.getFile() } + override ASTNode getAstNode() { result = pattern } } @@ -429,6 +439,8 @@ module DataFlow { override string toString() { result = elt.toString() } + override File getFile() { result = pattern.getFile() } + override ASTNode getAstNode() { result = elt } } @@ -456,6 +468,8 @@ module DataFlow { override string toString() { result = elt.toString() } + override File getFile() { result = arr.getFile() } + override ASTNode getAstNode() { result = elt } } @@ -478,6 +492,8 @@ module DataFlow { } override string toString() { result = "reflective call" } + + override File getFile() { result = call.getFile() } } /** @@ -497,6 +513,8 @@ module DataFlow { } override string toString() { result = imprt.toString() } + + override File getFile() { result = imprt.getFile() } } /** @@ -924,6 +942,8 @@ module DataFlow { ) { p.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + + override File getFile() { result = p.getFile() } } /** @@ -944,6 +964,8 @@ module DataFlow { /** Gets the attribute corresponding to this data flow node. */ HTML::Attribute getAttribute() { result = attr } + + override File getFile() { result = attr.getFile() } } /** @@ -968,6 +990,8 @@ module DataFlow { * Gets the function corresponding to this exceptional return node. */ Function getFunction() { result = function } + + override File getFile() { result = function.getFile() } } /** @@ -992,6 +1016,8 @@ module DataFlow { * Gets the invocation corresponding to this exceptional return node. */ DataFlow::InvokeNode getInvocation() { result = invoke.flow() } + + override File getFile() { result = invoke.getFile() } } /** @@ -1219,6 +1245,10 @@ module DataFlow { .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) ) } + + override File getFile() { + exists(StmtContainer container | this = TThisNode(container) | result = container.getFile()) + } } /** From 5da968e34c46e9f560f6f89701ebd1f5dc6d819b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 9 Apr 2020 10:47:15 +0100 Subject: [PATCH 416/459] JS: Specialize ASTNode.getFile --- javascript/ql/src/semmle/javascript/AST.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/src/semmle/javascript/AST.qll index b1cbe224764..81bb64f272c 100644 --- a/javascript/ql/src/semmle/javascript/AST.qll +++ b/javascript/ql/src/semmle/javascript/AST.qll @@ -23,6 +23,10 @@ import javascript class ASTNode extends @ast_node, Locatable { override Location getLocation() { hasLocation(this, result) } + override File getFile() { + result = getLocation().getFile() // Specialized for performance reasons + } + /** Gets the first token belonging to this element. */ Token getFirstToken() { exists(Location l1, Location l2 | From 88667206fcf1d78503227e6db52187435dc906b1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 9 Apr 2020 11:20:21 +0100 Subject: [PATCH 417/459] JS: Remove default hasLocationInfo case --- javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index b3b35142dd6..31ca34f1c0c 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -165,11 +165,7 @@ module DataFlow { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - filepath = "" and - startline = 0 and - startcolumn = 0 and - endline = 0 and - endcolumn = 0 + none() } /** Gets the file this data flow node comes from. */ From 3515a2b412c169c3b9966c3217ad38e6f3f8856e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 14 Apr 2020 10:31:31 +0100 Subject: [PATCH 418/459] JS: Update test output --- .../Refinement_getRefinedVar.expected | 4 +- .../SSA/GetRhsNode/GetRhsNode.expected | 28 +++--- .../AngularJS/modules/ModuleRef.expected | 24 ++--- .../variables/getDeclaringContainer.expected | 92 +++++++++---------- 4 files changed, 74 insertions(+), 74 deletions(-) diff --git a/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected b/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected index fcb1b6cbba0..6673b6e7cb3 100644 --- a/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected +++ b/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected @@ -1,2 +1,2 @@ -| tst.js:4:3:4:27 | (typeof ... nction' | x | -| tst.js:8:3:8:23 | (typeof ... === 'u' | x | +| tst.js:4:3:4:27 | (typeof ... nction' | tst.js:3:12:3:12 | x | +| tst.js:8:3:8:23 | (typeof ... === 'u' | tst.js:3:12:3:12 | x | diff --git a/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected b/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected index 7f37d2d2a11..e971020cdd6 100644 --- a/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected +++ b/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected @@ -1,14 +1,14 @@ -| tst.js:2:7:2:13 | a = g() | a | tst.js:2:11:2:13 | g() | -| tst.js:4:7:4:24 | { propB: b } = g() | b | tst.js:4:9:4:16 | propB: b | -| tst.js:6:7:6:34 | { propC ... } = g() | c | tst.js:6:9:6:16 | propC: c | -| tst.js:6:7:6:34 | { propC ... } = g() | d | tst.js:6:19:6:26 | propD: d | -| tst.js:8:7:8:41 | { array ... } = g() | elm1 | tst.js:8:22:8:25 | elm1 | -| tst.js:8:7:8:41 | { array ... } = g() | elm2 | tst.js:8:28:8:31 | elm2 | -| tst.js:17:3:17:22 | ({ propB: b }) = g() | b | tst.js:17:6:17:13 | propB: b | -| tst.js:19:3:19:32 | ({ prop ... ) = g() | c | tst.js:19:6:19:13 | propC: c | -| tst.js:19:3:19:32 | ({ prop ... ) = g() | d | tst.js:19:16:19:23 | propD: d | -| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | elm1 | tst.js:21:5:21:8 | elm1 | -| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | elm2 | tst.js:21:11:21:14 | elm2 | -| tst.js:31:12:31:23 | [elm1, elm2] | elm1 | tst.js:31:13:31:16 | elm1 | -| tst.js:31:12:31:23 | [elm1, elm2] | elm2 | tst.js:31:19:31:22 | elm2 | -| tst.js:31:26:31:40 | { prop: value } | value | tst.js:31:28:31:38 | prop: value | +| tst.js:2:7:2:13 | a = g() | tst.js:2:7:2:7 | a | tst.js:2:11:2:13 | g() | +| tst.js:4:7:4:24 | { propB: b } = g() | tst.js:4:16:4:16 | b | tst.js:4:9:4:16 | propB: b | +| tst.js:6:7:6:34 | { propC ... } = g() | tst.js:6:16:6:16 | c | tst.js:6:9:6:16 | propC: c | +| tst.js:6:7:6:34 | { propC ... } = g() | tst.js:6:26:6:26 | d | tst.js:6:19:6:26 | propD: d | +| tst.js:8:7:8:41 | { array ... } = g() | tst.js:8:22:8:25 | elm1 | tst.js:8:22:8:25 | elm1 | +| tst.js:8:7:8:41 | { array ... } = g() | tst.js:8:28:8:31 | elm2 | tst.js:8:28:8:31 | elm2 | +| tst.js:17:3:17:22 | ({ propB: b }) = g() | tst.js:4:16:4:16 | b | tst.js:17:6:17:13 | propB: b | +| tst.js:19:3:19:32 | ({ prop ... ) = g() | tst.js:6:16:6:16 | c | tst.js:19:6:19:13 | propC: c | +| tst.js:19:3:19:32 | ({ prop ... ) = g() | tst.js:6:26:6:26 | d | tst.js:19:16:19:23 | propD: d | +| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | tst.js:8:22:8:25 | elm1 | tst.js:21:5:21:8 | elm1 | +| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | tst.js:8:28:8:31 | elm2 | tst.js:21:11:21:14 | elm2 | +| tst.js:31:12:31:23 | [elm1, elm2] | tst.js:31:13:31:16 | elm1 | tst.js:31:13:31:16 | elm1 | +| tst.js:31:12:31:23 | [elm1, elm2] | tst.js:31:19:31:22 | elm2 | tst.js:31:19:31:22 | elm2 | +| tst.js:31:26:31:40 | { prop: value } | tst.js:31:34:31:38 | value | tst.js:31:28:31:38 | prop: value | diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected b/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected index bb82e314424..08ec97d5a9d 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected @@ -1,12 +1,12 @@ -| cm1 | -| cm2 | -| cm3 | -| cm4 | -| cm5 | -| cm6 | -| cm7 | -| cm8 | -| dm1 | -| m | -| mcm1 | -| rm1 | +| module-refs.js:3:9:3:11 | dm1 | +| module-refs.js:6:9:6:11 | rm1 | +| module-refs.js:9:9:9:11 | cm1 | +| module-refs.js:10:9:10:11 | cm2 | +| module-refs.js:11:9:11:11 | cm3 | +| module-refs.js:12:9:12:11 | cm4 | +| module-refs.js:13:9:13:11 | cm5 | +| module-refs.js:14:9:14:11 | cm6 | +| module-refs.js:15:9:15:11 | cm7 | +| module-refs.js:16:9:16:11 | cm8 | +| module-refs.js:22:9:22:12 | mcm1 | +| tst.js:19:7:19:7 | m | diff --git a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected index bf97e07b559..b9013913d10 100644 --- a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected +++ b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected @@ -1,46 +1,46 @@ -| arguments | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | -| arguments | assignments.js:3:1:6:1 | functio ... = 56;\\n} | -| arguments | assignments.js:4:10:4:24 | function h() {} | -| arguments | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| arguments | defaultargs.js:3:3:3:25 | functio ... = x) {} | -| arguments | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| arguments | for.js:1:2:5:1 | functio ... x;\\n} | -| arguments | let.js:14:1:21:1 | functio ... }\\n} | -| arguments | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | -| arguments | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | -| arguments | variables.js:8:1:12:1 | functio ... ar x;\\n} | -| arguments | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| arguments | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | -| f | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| g | assignments.js:3:1:6:1 | functio ... = 56;\\n} | -| g | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| g | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | -| h | assignments.js:4:10:4:24 | function h() {} | -| h | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| o | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | -| o | for.js:1:2:5:1 | functio ... x;\\n} | -| x | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | -| x | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| x | defaultargs.js:3:3:3:25 | functio ... = x) {} | -| x | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| x | for.js:1:2:5:1 | functio ... x;\\n} | -| x | legacyletstmt.js:1:1:8:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:14:1:21:1 | functio ... }\\n} | -| x | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | -| x | variables.js:8:1:12:1 | functio ... ar x;\\n} | -| x | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| y | defaultargs.js:3:3:3:25 | functio ... = x) {} | -| y | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| y | legacyletstmt.js:1:1:8:0 | | -| y | let.js:1:1:22:0 | | -| y | let.js:14:1:21:1 | functio ... }\\n} | -| y | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | -| y | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| y | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | -| z | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| z | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | +| arrayPatternDefault.js:1:2:1:1 | arguments | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | +| arrayPatternDefault.js:1:11:1:11 | o | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | +| arrayPatternDefault.js:2:8:2:8 | x | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | +| assignments.js:3:1:3:0 | arguments | assignments.js:3:1:6:1 | functio ... = 56;\\n} | +| assignments.js:4:6:4:6 | g | assignments.js:3:1:6:1 | functio ... = 56;\\n} | +| assignments.js:4:10:4:9 | arguments | assignments.js:4:10:4:24 | function h() {} | +| assignments.js:4:19:4:19 | h | assignments.js:4:10:4:24 | function h() {} | +| defaultargs.js:2:7:2:7 | x | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:2:10:2:18 | arguments | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:3:3:3:2 | arguments | defaultargs.js:3:3:3:25 | functio ... = x) {} | +| defaultargs.js:3:12:3:12 | f | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:3:14:3:14 | x | defaultargs.js:3:3:3:25 | functio ... = x) {} | +| defaultargs.js:3:17:3:17 | y | defaultargs.js:3:3:3:25 | functio ... = x) {} | +| defaultargs.js:4:3:4:2 | arguments | defaultargs.js:4:3:4:51 | functio ... [0]) {} | +| defaultargs.js:4:12:4:12 | g | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:4:14:4:14 | x | defaultargs.js:4:3:4:51 | functio ... [0]) {} | +| defaultargs.js:4:32:4:32 | y | defaultargs.js:4:3:4:51 | functio ... [0]) {} | +| for.js:1:2:1:1 | arguments | for.js:1:2:5:1 | functio ... x;\\n} | +| for.js:1:11:1:11 | o | for.js:1:2:5:1 | functio ... x;\\n} | +| for.js:2:7:2:7 | x | for.js:1:2:5:1 | functio ... x;\\n} | +| legacyletstmt.js:3:6:3:6 | x | legacyletstmt.js:1:1:8:0 | | +| legacyletstmt.js:3:14:3:14 | y | legacyletstmt.js:1:1:8:0 | | +| let.js:2:9:2:9 | x | let.js:1:1:22:0 | | +| let.js:4:13:4:13 | x | let.js:1:1:22:0 | | +| let.js:5:18:5:18 | x | let.js:1:1:22:0 | | +| let.js:5:26:5:26 | y | let.js:1:1:22:0 | | +| let.js:6:17:6:17 | x | let.js:1:1:22:0 | | +| let.js:9:18:9:18 | x | let.js:1:1:22:0 | | +| let.js:14:1:14:0 | arguments | let.js:14:1:21:1 | functio ... }\\n} | +| let.js:14:14:14:14 | x | let.js:14:1:21:1 | functio ... }\\n} | +| let.js:17:11:17:11 | y | let.js:14:1:21:1 | functio ... }\\n} | +| typeoftype.ts:1:1:1:0 | arguments | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | +| typeoftype.ts:2:7:2:7 | x | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | +| typeoftype.ts:3:3:3:2 | arguments | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | +| typeoftype.ts:3:12:3:12 | g | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | +| typeoftype.ts:4:9:4:9 | y | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | +| variables.js:8:1:8:0 | arguments | variables.js:8:1:12:1 | functio ... ar x;\\n} | +| variables.js:9:6:9:6 | x | variables.js:8:1:12:1 | functio ... ar x;\\n} | +| variables.js:13:1:13:0 | arguments | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:13:12:13:12 | y | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:13:15:13:15 | z | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:15:6:15:6 | x | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:16:2:16:1 | arguments | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | +| variables.js:16:11:16:11 | h | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:16:13:16:13 | z | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | +| variables.js:18:11:18:11 | y | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | From 419b511ddbca96875d6c72c1774930514508527d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 14 Apr 2020 11:39:44 +0200 Subject: [PATCH 419/459] C++: Format --- cpp/ql/src/Critical/LoopBounds.qll | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/Critical/LoopBounds.qll b/cpp/ql/src/Critical/LoopBounds.qll index 390655b004e..b2cde8d6fe8 100644 --- a/cpp/ql/src/Critical/LoopBounds.qll +++ b/cpp/ql/src/Critical/LoopBounds.qll @@ -2,15 +2,16 @@ import cpp -/** An assignment to a variable with the value `0`. For example: - * ``` - * int x; - * x = 0; - * ``` - * but not: - * ``` - * int x = 0; - * ``` +/** + * An assignment to a variable with the value `0`. For example: + * ``` + * int x; + * x = 0; + * ``` + * but not: + * ``` + * int x = 0; + * ``` */ class ZeroAssignment extends AssignExpr { ZeroAssignment() { From 92187d9e7189cd4bacb302202780eca932003c88 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 9 Apr 2020 17:45:38 +0100 Subject: [PATCH 420/459] C++: Change note. --- change-notes/1.24/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.24/analysis-cpp.md b/change-notes/1.24/analysis-cpp.md index 7ab002857cf..8f8c3d5364a 100644 --- a/change-notes/1.24/analysis-cpp.md +++ b/change-notes/1.24/analysis-cpp.md @@ -25,6 +25,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. | | No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. | | Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | Cases where the tainted allocation size is range checked are now more reliably excluded. | +| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | The query now produces fewer, more accurate results. | | Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. | | Unsafe array for days of the year (`cpp/leap-year/unsafe-array-for-days-of-the-year`) | | This query is no longer run on LGTM. | | Unsigned comparison to zero (`cpp/unsigned-comparison-zero`) | More correct results | This query now also looks for comparisons of the form `0 <= x`. | From c178eecd43a4fe84285c958e327fb75383798b90 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 14 Apr 2020 14:40:21 +0100 Subject: [PATCH 421/459] Update javascript/ql/src/semmle/javascript/Variables.qll Co-Authored-By: Erik Krogh Kristensen --- javascript/ql/src/semmle/javascript/Variables.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Variables.qll b/javascript/ql/src/semmle/javascript/Variables.qll index ede33788841..2cbd54d1d73 100644 --- a/javascript/ql/src/semmle/javascript/Variables.qll +++ b/javascript/ql/src/semmle/javascript/Variables.qll @@ -321,8 +321,8 @@ class LocalVariable extends Variable { /** * Gets the location of a declaration of this variable. * - * If the variable has multiple declarations, an arbitrary one is used. - * If it has no declaration, the entry point of its declaring container is used. + * If the variable has one or more declarations, the location of the first declaration is used. + * If the variable has no declaration, the entry point of its declaring container is used. */ Location getLocation() { result = From 83cd78c6cf84bf8a10e6ae1ffd19be61104ae142 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Tue, 14 Apr 2020 10:54:00 -0400 Subject: [PATCH 422/459] C++: Fix test output --- cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected | 1 + cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected | 1 + .../test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected | 1 + 3 files changed, 3 insertions(+) diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 362983363cc..fd988023d9a 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -539,6 +539,7 @@ unexplainedLoop | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | Load: x | | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | VariableAddress: x | unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index cd5366a0c73..cec5ca7d9ed 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -596,6 +596,7 @@ unexplainedLoop | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | Load: x | | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | VariableAddress: x | unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 82b5f5ccef0..3a6083ec684 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -548,6 +548,7 @@ unexplainedLoop | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | Load: x | | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | VariableAddress: x | unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges From 95a6dd01c6207d624a9d501ebbe325f2e309f751 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Tue, 14 Apr 2020 11:11:36 -0400 Subject: [PATCH 423/459] C#: Accept test output --- csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected | 1 + csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected | 1 + 2 files changed, 2 insertions(+) diff --git a/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected b/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected index c5a0b98598f..61bc9b2261c 100644 --- a/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected +++ b/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index c5a0b98598f..61bc9b2261c 100644 --- a/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges From 125a09ce6e2e1e3e10ec5d0cc2bfb6cd54bcc924 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Tue, 14 Apr 2020 11:40:33 -0400 Subject: [PATCH 424/459] C++: Fix IR generation of `return` of `void` expression --- .../raw/internal/TranslatedStmt.qll | 37 ++++++++++++++++++- .../library-tests/ir/ir/PrintAST.expected | 17 +++++++++ cpp/ql/test/library-tests/ir/ir/ir.cpp | 4 ++ .../test/library-tests/ir/ir/raw_ir.expected | 23 ++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index f7d060c7c64..a4c9d487437 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -135,7 +135,7 @@ abstract class TranslatedReturnStmt extends TranslatedStmt { * The IR translation of a `return` statement that returns a value. */ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariableInitialization { - TranslatedReturnValueStmt() { stmt.hasExpr() } + TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) } final override Instruction getInitializationSuccessor() { result = getEnclosingFunction().getReturnSuccessorInstruction() @@ -150,6 +150,41 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() } } +/** + * The IR translation of a `return` statement that returns an expression of `void` type. + */ +class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt { + TranslatedReturnVoidExpressionStmt() { + stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction()) + } + + override TranslatedElement getChild(int id) { + id = 0 and + result = getExpr() + } + + override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::NoOp and + resultType = getVoidType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = OnlyInstructionTag() and + result = getEnclosingFunction().getReturnSuccessorInstruction() and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getExpr() and + result = getInstruction(OnlyInstructionTag()) + } + + private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) } +} + /** * The IR translation of a `return` statement that does not return a value. This includes implicit * return statements at the end of `void`-returning functions. diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index e2a02352f0f..268371ab3d5 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -8767,6 +8767,23 @@ ir.cpp: # 1291| Type = [IntType] int # 1291| ValueCategory = prvalue(load) # 1293| 1: [ReturnStmt] return ... +# 1295| [TopLevelFunction] void returnVoid(int, int) +# 1295| params: +# 1295| 0: [Parameter] x +# 1295| Type = [IntType] int +# 1295| 1: [Parameter] y +# 1295| Type = [IntType] int +# 1295| body: [Block] { ... } +# 1296| 0: [ReturnStmt] return ... +# 1296| 0: [FunctionCall] call to IntegerOps +# 1296| Type = [VoidType] void +# 1296| ValueCategory = prvalue +# 1296| 0: [VariableAccess] x +# 1296| Type = [IntType] int +# 1296| ValueCategory = prvalue(load) +# 1296| 1: [VariableAccess] y +# 1296| Type = [IntType] int +# 1296| ValueCategory = prvalue(load) perf-regression.cpp: # 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&) # 4| params: diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index e40c4c095d6..cdebee29aea 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1292,4 +1292,8 @@ int missingReturnValue(bool b, int x) { } } +void returnVoid(int x, int y) { + return IntegerOps(x, y); +} + // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 344269ec7db..bc5fbd5b4d2 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -6661,6 +6661,29 @@ ir.cpp: # 1289| v1289_12(void) = AliasedUse : ~mu1289_4 # 1289| v1289_13(void) = ExitFunction : +# 1295| void returnVoid(int, int) +# 1295| Block 0 +# 1295| v1295_1(void) = EnterFunction : +# 1295| mu1295_2(unknown) = AliasedDefinition : +# 1295| mu1295_3(unknown) = InitializeNonLocal : +# 1295| mu1295_4(unknown) = UnmodeledDefinition : +# 1295| r1295_5(glval) = VariableAddress[x] : +# 1295| mu1295_6(int) = InitializeParameter[x] : &:r1295_5 +# 1295| r1295_7(glval) = VariableAddress[y] : +# 1295| mu1295_8(int) = InitializeParameter[y] : &:r1295_7 +# 1296| r1296_1(glval) = FunctionAddress[IntegerOps] : +# 1296| r1296_2(glval) = VariableAddress[x] : +# 1296| r1296_3(int) = Load : &:r1296_2, ~mu1295_4 +# 1296| r1296_4(glval) = VariableAddress[y] : +# 1296| r1296_5(int) = Load : &:r1296_4, ~mu1295_4 +# 1296| v1296_6(void) = Call : func:r1296_1, 0:r1296_3, 1:r1296_5 +# 1296| mu1296_7(unknown) = ^CallSideEffect : ~mu1295_4 +# 1296| v1296_8(void) = NoOp : +# 1295| v1295_9(void) = ReturnVoid : +# 1295| v1295_10(void) = UnmodeledUse : mu* +# 1295| v1295_11(void) = AliasedUse : ~mu1295_4 +# 1295| v1295_12(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0 From 092145d5712b1573242e160db20ac164030fa21b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 14 Apr 2020 18:38:33 +0200 Subject: [PATCH 425/459] Update cpp/ql/src/Critical/FileClosed.qll Co-Authored-By: Jonas Jensen --- cpp/ql/src/Critical/FileClosed.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Critical/FileClosed.qll b/cpp/ql/src/Critical/FileClosed.qll index a58af50ba67..e2ba3c25b81 100644 --- a/cpp/ql/src/Critical/FileClosed.qll +++ b/cpp/ql/src/Critical/FileClosed.qll @@ -17,7 +17,7 @@ class ClosedExpr extends PointsToExpr { } /** - * Holds if `fc` is a call to function that opens a file which might be closed. For example: + * Holds if `fc` is a call to a function that opens a file that might be closed. For example: * ``` * FILE* f = fopen("file.txt", "r"); * ... From 7f5b3de6657c9b845259ff3504a10d787b2220b0 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 14 Apr 2020 10:36:53 -0700 Subject: [PATCH 426/459] C++: autoformat --- cpp/ql/src/semmle/code/cpp/Comments.qll | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Comments.qll b/cpp/ql/src/semmle/code/cpp/Comments.qll index 1558bf95477..7f961bfd6f6 100644 --- a/cpp/ql/src/semmle/code/cpp/Comments.qll +++ b/cpp/ql/src/semmle/code/cpp/Comments.qll @@ -1,5 +1,3 @@ - - import semmle.code.cpp.Location import semmle.code.cpp.Element From 5ee60762fef3897a15ac8c0f7ab8aab84ca5f925 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 14 Apr 2020 10:49:52 -0700 Subject: [PATCH 427/459] C++: deprecate Declaration::isDefined() --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 1d5603fe4f4..31774170b6c 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -161,6 +161,7 @@ abstract class Declaration extends Locatable, @declaration { /** Holds if the declaration has a definition. */ predicate hasDefinition() { exists(this.getDefinition()) } + /** DEPRECATED: Use `hasDefinition` instead. */ predicate isDefined() { hasDefinition() } /** Gets the preferred location of this declaration, if any. */ From b5c0a0f77ddc6d45dd8854b5a0a5ab41247a0b94 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 14 Apr 2020 10:53:43 -0700 Subject: [PATCH 428/459] C++: remove all uses of Declaration::isDefined --- cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql | 2 +- .../Security/CWE/CWE-457/InitializationFunctions.qll | 12 ++++++------ cpp/ql/src/semmle/code/cpp/Declaration.qll | 2 +- cpp/ql/src/semmle/code/cpp/UserType.qll | 2 +- .../code/cpp/security/FunctionWithWrappers.qll | 2 +- .../templates/prototype_bodies/isdef_hasblock.ql | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql index 72852f0b86c..965bb8440b0 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql @@ -30,7 +30,7 @@ predicate allowedTypedefs(TypedefType t) { * Gets a type which appears literally in the declaration of `d`. */ Type getAnImmediateUsedType(Declaration d) { - d.isDefined() and + d.hasDefinition() and ( result = d.(Function).getType() or result = d.(Variable).getType() diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index a10e3df0bdd..c5285fdac57 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -198,12 +198,12 @@ class InitializationFunction extends Function { ) or // If we have no definition, we look at SAL annotations - not this.isDefined() and + not this.hasDefinition() and this.getParameter(i).(SALParameter).isOut() and evidence = SuggestiveSALAnnotation() or // We have some external information that this function conditionally initializes - not this.isDefined() and + not this.hasDefinition() and any(ValidatedExternalCondInitFunction vc).isExternallyVerified(this, i) and evidence = ExternalEvidence() } @@ -406,7 +406,7 @@ class ConditionalInitializationFunction extends InitializationFunction { * Explicitly ignore pure virtual functions. */ - this.isDefined() and + this.hasDefinition() and this.paramNotReassignedAt(this, i, c) and not this instanceof PureVirtualFunction ) @@ -616,11 +616,11 @@ private predicate functionSignature(Function f, string qualifiedName, string typ * are never statically linked together. */ private Function getAPossibleDefinition(Function undefinedFunction) { - not undefinedFunction.isDefined() and + not undefinedFunction.hasDefinition() and exists(string qn, string typeSig | functionSignature(undefinedFunction, qn, typeSig) and functionSignature(result, qn, typeSig) ) and - result.isDefined() + result.hasDefinition() } /** @@ -631,7 +631,7 @@ private Function getAPossibleDefinition(Function undefinedFunction) { */ private Function getTarget1(Call c) { result = VirtualDispatch::getAViableTarget(c) and - result.isDefined() + result.hasDefinition() } /** diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 31774170b6c..a0eaa7fa1d0 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -304,7 +304,7 @@ abstract class DeclarationEntry extends Locatable { * available), or the name declared by this entry otherwise. */ string getCanonicalName() { - if getDeclaration().isDefined() + if getDeclaration().hasDefinition() then result = getDeclaration().getDefinition().getName() else result = getName() } diff --git a/cpp/ql/src/semmle/code/cpp/UserType.qll b/cpp/ql/src/semmle/code/cpp/UserType.qll index cbb7f39adbd..4484cde84de 100644 --- a/cpp/ql/src/semmle/code/cpp/UserType.qll +++ b/cpp/ql/src/semmle/code/cpp/UserType.qll @@ -38,7 +38,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ override Specifier getASpecifier() { result = Type.super.getASpecifier() } override Location getLocation() { - if isDefined() + if hasDefinition() then result = this.getDefinitionLocation() else result = this.getADeclarationLocation() } diff --git a/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll b/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll index 8047bc384b2..23dda0ddb1e 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll @@ -19,7 +19,7 @@ private predicate wrapperFunctionStep( ) { not target.isVirtual() and not source.isVirtual() and - source.isDefined() and + source.hasDefinition() and exists(Call call, Expr arg, Parameter sourceParam | // there is a 'call' to 'target' with argument 'arg' at index 'targetParamIndex' target = resolveCall(call) and diff --git a/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql b/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql index c9cccbf24ae..be844bcf185 100644 --- a/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql +++ b/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql @@ -3,6 +3,6 @@ import cpp // It should be the case that "f.isDefined()" is equivalent to "exists(f.getBlock())". from Function f, string isdef, string hasblock where - (if f.isDefined() then isdef = "defined" else isdef = "not defined") and + (if f.hasDefinition() then isdef = "defined" else isdef = "not defined") and (if exists(f.getBlock()) then hasblock = "has block" else hasblock = "no block") select f.getName(), isdef, hasblock From 812087968f4ece49672227eba19a9611435a3ebf Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Tue, 14 Apr 2020 14:17:20 -0400 Subject: [PATCH 429/459] C++: Fix test output Mostly noise, but a couple of the missing operand errors are actual fixes. --- .../syntax-zoo/aliased_ssa_sanity.expected | 345 +++++++++--------- .../dataflow-ir-consistency.expected | 6 - .../syntax-zoo/raw_sanity.expected | 345 +++++++++--------- .../syntax-zoo/unaliased_ssa_sanity.expected | 345 +++++++++--------- 4 files changed, 505 insertions(+), 536 deletions(-) diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 362983363cc..7658b7f83f5 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -30,7 +30,6 @@ missingOperand unexpectedOperand duplicateOperand missingPhiOperand -| cpp11.cpp:141:7:141:7 | Phi: g | cpp11.cpp:161:16:161:16 | NoOp: label ...: | missingOperandType duplicateChiOperand sideEffectWithoutPrimary @@ -83,50 +82,48 @@ ambiguousSuccessors | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | conditional_destructors.cpp:30:9:30:13 | FunctionAddress: call to C1 | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | forstmt.cpp:2:14:2:14 | VariableAddress: definition of i | | conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition: f2 | Goto | 2 | conditional_destructors.cpp:39:9:39:13 | FunctionAddress: call to C2 | @@ -213,50 +210,48 @@ ambiguousSuccessors | dostmt.c:16:6:16:18 | UnmodeledDefinition: always_true_2 | Goto | 4 | whilestmt.c:24:9:24:9 | Constant: 1 | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | dostmt.c:27:5:27:7 | NoOp: label ...: | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | whilestmt.c:33:9:33:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c | @@ -361,50 +356,48 @@ ambiguousSuccessors | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | | parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo | @@ -463,50 +456,48 @@ ambiguousSuccessors | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifelsestmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifstmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | whilestmt.c:2:9:2:9 | Constant: 0 | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index b569b63cb61..f3e74c759b6 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -1,11 +1,5 @@ uniqueEnclosingCallable uniqueTypeBound -| break_labels.c:13:5:13:18 | VariableAddress | Node should have one type bound but has 2. | -| break_labels.c:13:12:13:17 | Store | Node should have one type bound but has 2. | -| enum.c:6:2:6:10 | VariableAddress | Node should have one type bound but has 2. | -| enum.c:6:9:6:9 | Store | Node should have one type bound but has 2. | -| parameterinitializer.cpp:4:5:4:13 | VariableAddress | Node should have one type bound but has 2. | -| parameterinitializer.cpp:4:12:4:12 | Store | Node should have one type bound but has 2. | uniqueTypeRepr uniqueNodeLocation | aggregateinitializer.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index cd5366a0c73..39d1fd19465 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -60,6 +60,7 @@ instructionWithoutSuccessor | condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | | cpp17.cpp:15:5:15:45 | InitializeDynamicAllocation: new | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | +| enum.c:6:9:6:9 | Constant: (int)... | | file://:0:0:0:0 | CompareNE: (bool)... | | file://:0:0:0:0 | CompareNE: (bool)... | | file://:0:0:0:0 | CompareNE: (bool)... | @@ -140,50 +141,48 @@ ambiguousSuccessors | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | conditional_destructors.cpp:30:9:30:13 | FunctionAddress: call to C1 | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | forstmt.cpp:2:14:2:14 | VariableAddress: definition of i | | conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition: f2 | Goto | 2 | conditional_destructors.cpp:39:9:39:13 | FunctionAddress: call to C2 | @@ -270,50 +269,48 @@ ambiguousSuccessors | dostmt.c:16:6:16:18 | UnmodeledDefinition: always_true_2 | Goto | 4 | whilestmt.c:24:9:24:9 | Constant: 1 | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | dostmt.c:27:5:27:7 | NoOp: label ...: | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | whilestmt.c:33:9:33:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c | @@ -418,50 +415,48 @@ ambiguousSuccessors | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | | parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo | @@ -520,50 +515,48 @@ ambiguousSuccessors | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifelsestmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifstmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | whilestmt.c:2:9:2:9 | Constant: 0 | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 82b5f5ccef0..98d70df2f53 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -30,7 +30,6 @@ missingOperand unexpectedOperand duplicateOperand missingPhiOperand -| cpp11.cpp:141:7:141:7 | Phi: g | cpp11.cpp:161:16:161:16 | NoOp: label ...: | | range_analysis.c:373:3:373:47 | Phi: return ... | range_analysis.c:371:37:371:39 | Constant: 500 | | range_analysis.c:373:3:373:47 | Phi: return ... | range_analysis.c:371:37:371:39 | Constant: 500 | | range_analysis.c:373:3:373:47 | Phi: return ... | range_analysis.c:371:37:371:39 | Constant: 500 | @@ -92,50 +91,48 @@ ambiguousSuccessors | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | conditional_destructors.cpp:30:9:30:13 | FunctionAddress: call to C1 | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | forstmt.cpp:2:14:2:14 | VariableAddress: definition of i | | conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition: f2 | Goto | 2 | conditional_destructors.cpp:39:9:39:13 | FunctionAddress: call to C2 | @@ -222,50 +219,48 @@ ambiguousSuccessors | dostmt.c:16:6:16:18 | UnmodeledDefinition: always_true_2 | Goto | 4 | whilestmt.c:24:9:24:9 | Constant: 1 | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | dostmt.c:27:5:27:7 | NoOp: label ...: | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | whilestmt.c:33:9:33:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c | @@ -370,50 +365,48 @@ ambiguousSuccessors | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | | parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo | @@ -472,50 +465,48 @@ ambiguousSuccessors | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifelsestmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifstmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | whilestmt.c:2:9:2:9 | Constant: 0 | From 279467654ecabf20a92e8e89d45a2ad9d56133cb Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Tue, 14 Apr 2020 14:17:56 -0400 Subject: [PATCH 430/459] C++: Make test functions return `void` --- .../GlobalValueNumbering/ir_gvn.expected | 116 ++++++++---------- .../GlobalValueNumbering/test.cpp | 8 +- 2 files changed, 58 insertions(+), 66 deletions(-) diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index a492fb47d41..e585bd806eb 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -1,80 +1,78 @@ test.cpp: -# 1| int test00(int, int) +# 1| void test00(int, int) # 1| Block 0 -# 1| v1_1(void) = EnterFunction : -# 1| m1_2(unknown) = AliasedDefinition : +# 1| v1_1(void) = EnterFunction : +# 1| m1_2(unknown) = AliasedDefinition : # 1| valnum = unique -# 1| m1_3(unknown) = InitializeNonLocal : +# 1| m1_3(unknown) = InitializeNonLocal : # 1| valnum = unique -# 1| m1_4(unknown) = Chi : total:m1_2, partial:m1_3 +# 1| m1_4(unknown) = Chi : total:m1_2, partial:m1_3 # 1| valnum = unique -# 1| mu1_5(unknown) = UnmodeledDefinition : +# 1| mu1_5(unknown) = UnmodeledDefinition : # 1| valnum = unique -# 1| r1_6(glval) = VariableAddress[p0] : +# 1| r1_6(glval) = VariableAddress[p0] : # 1| valnum = r1_6, r5_1, r6_1 -# 1| m1_7(int) = InitializeParameter[p0] : &:r1_6 +# 1| m1_7(int) = InitializeParameter[p0] : &:r1_6 # 1| valnum = m1_7, r5_2, r6_2 -# 1| r1_8(glval) = VariableAddress[p1] : +# 1| r1_8(glval) = VariableAddress[p1] : # 1| valnum = r1_8, r5_3, r6_3 -# 1| m1_9(int) = InitializeParameter[p1] : &:r1_8 +# 1| m1_9(int) = InitializeParameter[p1] : &:r1_8 # 1| valnum = m1_9, r5_4, r6_4 -# 2| r2_1(glval) = VariableAddress[x] : +# 2| r2_1(glval) = VariableAddress[x] : # 2| valnum = r2_1, r5_6, r6_6, r7_1 -# 2| m2_2(int) = Uninitialized[x] : &:r2_1 +# 2| m2_2(int) = Uninitialized[x] : &:r2_1 # 2| valnum = unique -# 2| r2_3(glval) = VariableAddress[y] : +# 2| r2_3(glval) = VariableAddress[y] : # 2| valnum = r2_3, r7_3 -# 2| m2_4(int) = Uninitialized[y] : &:r2_3 +# 2| m2_4(int) = Uninitialized[y] : &:r2_3 # 2| valnum = unique -# 3| r3_1(glval) = VariableAddress[b] : +# 3| r3_1(glval) = VariableAddress[b] : # 3| valnum = unique -# 3| m3_2(unsigned char) = Uninitialized[b] : &:r3_1 +# 3| m3_2(unsigned char) = Uninitialized[b] : &:r3_1 # 3| valnum = unique -# 5| r5_1(glval) = VariableAddress[p0] : +# 5| r5_1(glval) = VariableAddress[p0] : # 5| valnum = r1_6, r5_1, r6_1 -# 5| r5_2(int) = Load : &:r5_1, m1_7 +# 5| r5_2(int) = Load : &:r5_1, m1_7 # 5| valnum = m1_7, r5_2, r6_2 -# 5| r5_3(glval) = VariableAddress[p1] : +# 5| r5_3(glval) = VariableAddress[p1] : # 5| valnum = r1_8, r5_3, r6_3 -# 5| r5_4(int) = Load : &:r5_3, m1_9 +# 5| r5_4(int) = Load : &:r5_3, m1_9 # 5| valnum = m1_9, r5_4, r6_4 -# 5| r5_5(int) = Add : r5_2, r5_4 +# 5| r5_5(int) = Add : r5_2, r5_4 # 5| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 5| r5_6(glval) = VariableAddress[x] : +# 5| r5_6(glval) = VariableAddress[x] : # 5| valnum = r2_1, r5_6, r6_6, r7_1 -# 5| m5_7(int) = Store : &:r5_6, r5_5 +# 5| m5_7(int) = Store : &:r5_6, r5_5 # 5| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 6| r6_1(glval) = VariableAddress[p0] : +# 6| r6_1(glval) = VariableAddress[p0] : # 6| valnum = r1_6, r5_1, r6_1 -# 6| r6_2(int) = Load : &:r6_1, m1_7 +# 6| r6_2(int) = Load : &:r6_1, m1_7 # 6| valnum = m1_7, r5_2, r6_2 -# 6| r6_3(glval) = VariableAddress[p1] : +# 6| r6_3(glval) = VariableAddress[p1] : # 6| valnum = r1_8, r5_3, r6_3 -# 6| r6_4(int) = Load : &:r6_3, m1_9 +# 6| r6_4(int) = Load : &:r6_3, m1_9 # 6| valnum = m1_9, r5_4, r6_4 -# 6| r6_5(int) = Add : r6_2, r6_4 +# 6| r6_5(int) = Add : r6_2, r6_4 # 6| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 6| r6_6(glval) = VariableAddress[x] : +# 6| r6_6(glval) = VariableAddress[x] : # 6| valnum = r2_1, r5_6, r6_6, r7_1 -# 6| m6_7(int) = Store : &:r6_6, r6_5 +# 6| m6_7(int) = Store : &:r6_6, r6_5 # 6| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 7| r7_1(glval) = VariableAddress[x] : +# 7| r7_1(glval) = VariableAddress[x] : # 7| valnum = r2_1, r5_6, r6_6, r7_1 -# 7| r7_2(int) = Load : &:r7_1, m6_7 +# 7| r7_2(int) = Load : &:r7_1, m6_7 # 7| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_3(glval) = VariableAddress[y] : # 7| valnum = r2_3, r7_3 -# 7| m7_4(int) = Store : &:r7_3, r7_2 +# 7| m7_4(int) = Store : &:r7_3, r7_2 # 7| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 8| v8_1(void) = NoOp : -# 1| r1_10(glval) = VariableAddress[#return] : -# 1| valnum = unique -# 1| v1_11(void) = ReturnValue : &:r1_10 -# 1| v1_12(void) = UnmodeledUse : mu* -# 1| v1_13(void) = AliasedUse : m1_3 -# 1| v1_14(void) = ExitFunction : +# 8| v8_1(void) = NoOp : +# 1| v1_10(void) = ReturnVoid : +# 1| v1_11(void) = UnmodeledUse : mu* +# 1| v1_12(void) = AliasedUse : m1_3 +# 1| v1_13(void) = ExitFunction : -# 12| int test01(int, int) +# 12| void test01(int, int) # 12| Block 0 # 12| v12_1(void) = EnterFunction : # 12| m12_2(unknown) = AliasedDefinition : @@ -154,14 +152,12 @@ test.cpp: # 18| m18_4(int) = Store : &:r18_3, r18_2 # 18| valnum = m16_10, m17_10, m18_4, r16_8, r17_8, r18_2 # 19| v19_1(void) = NoOp : -# 12| r12_10(glval) = VariableAddress[#return] : -# 12| valnum = unique -# 12| v12_11(void) = ReturnValue : &:r12_10 -# 12| v12_12(void) = UnmodeledUse : mu* -# 12| v12_13(void) = AliasedUse : m12_3 -# 12| v12_14(void) = ExitFunction : +# 12| v12_10(void) = ReturnVoid : +# 12| v12_11(void) = UnmodeledUse : mu* +# 12| v12_12(void) = AliasedUse : m12_3 +# 12| v12_13(void) = ExitFunction : -# 25| int test02(int, int) +# 25| void test02(int, int) # 25| Block 0 # 25| v25_1(void) = EnterFunction : # 25| m25_2(unknown) = AliasedDefinition : @@ -248,14 +244,12 @@ test.cpp: # 32| m32_4(int) = Store : &:r32_3, r32_2 # 32| valnum = m31_10, m32_4, r31_8, r32_2 # 33| v33_1(void) = NoOp : -# 25| r25_10(glval) = VariableAddress[#return] : -# 25| valnum = unique -# 25| v25_11(void) = ReturnValue : &:r25_10 -# 25| v25_12(void) = UnmodeledUse : mu* -# 25| v25_13(void) = AliasedUse : ~m30_4 -# 25| v25_14(void) = ExitFunction : +# 25| v25_10(void) = ReturnVoid : +# 25| v25_11(void) = UnmodeledUse : mu* +# 25| v25_12(void) = AliasedUse : ~m30_4 +# 25| v25_13(void) = ExitFunction : -# 39| int test03(int, int, int*) +# 39| void test03(int, int, int*) # 39| Block 0 # 39| v39_1(void) = EnterFunction : # 39| m39_2(unknown) = AliasedDefinition : @@ -356,12 +350,10 @@ test.cpp: # 46| valnum = m43_10, m45_10, m46_4, r43_8, r45_8, r46_2 # 47| v47_1(void) = NoOp : # 39| v39_14(void) = ReturnIndirection : &:r39_12, m44_6 -# 39| r39_15(glval) = VariableAddress[#return] : -# 39| valnum = unique -# 39| v39_16(void) = ReturnValue : &:r39_15 -# 39| v39_17(void) = UnmodeledUse : mu* -# 39| v39_18(void) = AliasedUse : m39_3 -# 39| v39_19(void) = ExitFunction : +# 39| v39_15(void) = ReturnVoid : +# 39| v39_16(void) = UnmodeledUse : mu* +# 39| v39_17(void) = AliasedUse : m39_3 +# 39| v39_18(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp index 3e878ac2356..dfef91006e3 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp @@ -1,4 +1,4 @@ -int test00(int p0, int p1) { +void test00(int p0, int p1) { int x, y; unsigned char b; @@ -9,7 +9,7 @@ int test00(int p0, int p1) { int global01 = 1; -int test01(int p0, int p1) { +void test01(int p0, int p1) { int x, y; unsigned char b; @@ -22,7 +22,7 @@ int global02 = 2; void change_global02(); // Just a declaration -int test02(int p0, int p1) { +void test02(int p0, int p1) { int x, y; unsigned char b; @@ -36,7 +36,7 @@ int global03 = 3; void change_global03(); // Just a declaration -int test03(int p0, int p1, int* p2) { +void test03(int p0, int p1, int* p2) { int x, y; unsigned char b; From 1107e7c6a6f9b7e529da21378e23183c138736a1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 14 Apr 2020 19:45:09 +0100 Subject: [PATCH 431/459] JS: Rename other uses of getURL --- javascript/ql/src/semmle/javascript/NPM.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/NPM.qll b/javascript/ql/src/semmle/javascript/NPM.qll index 1038b04b6c2..24d3072fae1 100644 --- a/javascript/ql/src/semmle/javascript/NPM.qll +++ b/javascript/ql/src/semmle/javascript/NPM.qll @@ -233,7 +233,7 @@ class ContributorInfo extends JSONValue { } /** Gets the contributor's homepage URL. */ - string getURL() { + string getUrl() { result = this.(JSONObject).getPropStringValue("url") or result = parseInfo(3) } @@ -249,7 +249,7 @@ class RepositoryInfo extends JSONObject { string getType() { result = getPropStringValue("type") } /** Gets the repository URL. */ - string getURL() { result = getPropStringValue("url") } + string getUrl() { result = getPropStringValue("url") } } /** From a2fbe9e9dad54118a86b22c2f93b7060f91bb794 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 14 Apr 2020 17:22:03 +0200 Subject: [PATCH 432/459] C++: Add QLDoc to public predicates in Negativity --- cpp/ql/src/Critical/Negativity.qll | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/cpp/ql/src/Critical/Negativity.qll b/cpp/ql/src/Critical/Negativity.qll index 161fe234967..2eb6906573f 100644 --- a/cpp/ql/src/Critical/Negativity.qll +++ b/cpp/ql/src/Critical/Negativity.qll @@ -1,10 +1,19 @@ import cpp +/** + * Holds if `val` is an access to the variable `v`, or if `val` + * is an assignment with an access to `v` on the left-hand side. + */ predicate valueOfVar(Variable v, Expr val) { val = v.getAnAccess() or val.(AssignExpr).getLValue() = v.getAnAccess() } +/** + * Holds if either: + * - `cond` is an (in)equality expression that compares the variable `v` to the value `-1`, or + * - `cond` is a relational expression that compares the variable `v` to a constant. + */ predicate boundsCheckExpr(Variable v, Expr cond) { exists(EQExpr eq | cond = eq and @@ -43,6 +52,18 @@ predicate boundsCheckExpr(Variable v, Expr cond) { ) } +/** + * Holds if `node` is an expression in a conditional statement and `succ` is an + * immediate successor of `node` that may be reached after evaluating `node`. + * For example, given + * ``` + * if (a < 10 && b) func1(); + * else func2(); + * ``` + * this predicate holds when either: + * - `node` is `a < 10` and `succ` is `func2()` or `b`, or + * - `node` is `b` and `succ` is `func1()` or `func2()` + */ predicate conditionalSuccessor(ControlFlowNode node, ControlFlowNode succ) { if node.isCondition() then succ = node.getATrueSuccessor() or succ = node.getAFalseSuccessor() @@ -52,6 +73,12 @@ predicate conditionalSuccessor(ControlFlowNode node, ControlFlowNode succ) { ) } +/** + * Holds if the current value of the variable `v` at control-flow + * node `n` has been used either in: + * - an (in)equality comparison with the value `-1`, or + * - a relational comparison that compares `v` to a constant. + */ predicate boundsChecked(Variable v, ControlFlowNode node) { exists(Expr test | boundsCheckExpr(v, test) and @@ -63,6 +90,14 @@ predicate boundsChecked(Variable v, ControlFlowNode node) { ) } +/** + * Holds if `cond` compares `v` to some common error values. Specifically, this + * predicate holds when: + * - `cond` checks that `v` is equal to `-1`, or + * - `cond` checks that `v` is less than `0`, or + * - `cond` checks that `v` is less than or equal to `-1`, or + * - `cond` checks that `v` is not some common success value (see `successCondition`). + */ predicate errorCondition(Variable v, Expr cond) { exists(EQExpr eq | cond = eq and @@ -88,6 +123,14 @@ predicate errorCondition(Variable v, Expr cond) { ) } +/** + * Holds if `cond` compares `v` to some common success values. Specifically, this + * predicate holds when: + * - `cond` checks that `v` is not equal to `-1`, or + * - `cond` checks that `v` is greater than or equal than `0`, or + * - `cond` checks that `v` is greater than `-1`, or + * - `cond` checks that `v` is not some common success value (see `errorCondition`). + */ predicate successCondition(Variable v, Expr cond) { exists(NEExpr ne | cond = ne and @@ -113,6 +156,11 @@ predicate successCondition(Variable v, Expr cond) { ) } +/** + * Holds if there exists a comparison operation that checks whether `v` + * represents some common *error* values, and `n` may be reached + * immediately following the comparison operation. + */ predicate errorSuccessor(Variable v, ControlFlowNode n) { exists(Expr cond | errorCondition(v, cond) and n = cond.getATrueSuccessor() @@ -121,6 +169,11 @@ predicate errorSuccessor(Variable v, ControlFlowNode n) { ) } +/** + * Holds if there exists a comparison operation that checks whether `v` + * represents some common *success* values, and `n` may be reached + * immediately following the comparison operation. + */ predicate successSuccessor(Variable v, ControlFlowNode n) { exists(Expr cond | successCondition(v, cond) and n = cond.getATrueSuccessor() @@ -129,6 +182,10 @@ predicate successSuccessor(Variable v, ControlFlowNode n) { ) } +/** + * Holds if the current value of the variable `v` at control-flow node + * `n` may have been checked against a common set of *error* values. + */ predicate checkedError(Variable v, ControlFlowNode n) { errorSuccessor(v, n) or @@ -139,6 +196,10 @@ predicate checkedError(Variable v, ControlFlowNode n) { ) } +/** + * Holds if the current value of the variable `v` at control-flow node + * `n` may have been checked against a common set of *error* values. + */ predicate checkedSuccess(Variable v, ControlFlowNode n) { successSuccessor(v, n) or From f02feac33a36c27363f748f5bc4e0e32ac2124b3 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 15 Apr 2020 11:34:19 +0200 Subject: [PATCH 433/459] C++: Add flow from #3220 --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 3 ++ .../dataflow/fields/ir-flow.expected | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index cfe1196d5e9..c5c994a8509 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -430,6 +430,9 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // for now. iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or + iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and + not iTo.isResultConflated() + or exists(ChiInstruction chi | iFrom = chi | not chi.isResultConflated() and iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected index 15a6d699adb..7a6432e29f3 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -1,4 +1,21 @@ edges +| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] | +| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] | +| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store | +| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c | +| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c | +| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] | +| A.cpp:154:13:154:13 | c | A.cpp:154:10:154:13 | (void *)... | +| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | +| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] | +| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store | +| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | +| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] | +| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store | +| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 | +| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] | +| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 | +| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:26:19:26:20 | Chi [m1] | | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | | aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] | @@ -11,6 +28,26 @@ edges | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | nodes +| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] | +| A.cpp:142:7:142:20 | Store | semmle.label | Store | +| A.cpp:142:14:142:20 | new | semmle.label | new | +| A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] | +| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] | +| A.cpp:154:10:154:13 | (void *)... | semmle.label | (void *)... | +| A.cpp:154:13:154:13 | c | semmle.label | c | +| A.cpp:154:13:154:13 | c | semmle.label | c | +| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store | +| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:13:3:13:21 | Store | semmle.label | Store | +| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] | +| aliasing.cpp:26:19:26:20 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] | +| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 | +| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | | aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | | aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input | @@ -31,6 +68,10 @@ nodes | struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | | struct_init.c:31:23:31:23 | a | semmle.label | a | #select +| A.cpp:154:10:154:13 | (void *)... | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | (void *)... | (void *)... flows from $@ | A.cpp:142:14:142:20 | new | new | +| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | +| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input | +| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input | | aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input | call to user_input | | aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input | call to user_input | | aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input | From 3d0ac53266fb4d650d8406588542cb53090e0fd3 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Wed, 15 Apr 2020 14:01:49 +0200 Subject: [PATCH 434/459] Apply suggestions from code review Co-Authored-By: Jonas Jensen --- cpp/ql/src/Critical/Negativity.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Critical/Negativity.qll b/cpp/ql/src/Critical/Negativity.qll index 2eb6906573f..e9c0a3d2410 100644 --- a/cpp/ql/src/Critical/Negativity.qll +++ b/cpp/ql/src/Critical/Negativity.qll @@ -129,7 +129,7 @@ predicate errorCondition(Variable v, Expr cond) { * - `cond` checks that `v` is not equal to `-1`, or * - `cond` checks that `v` is greater than or equal than `0`, or * - `cond` checks that `v` is greater than `-1`, or - * - `cond` checks that `v` is not some common success value (see `errorCondition`). + * - `cond` checks that `v` is not some common error value (see `errorCondition`). */ predicate successCondition(Variable v, Expr cond) { exists(NEExpr ne | @@ -198,7 +198,7 @@ predicate checkedError(Variable v, ControlFlowNode n) { /** * Holds if the current value of the variable `v` at control-flow node - * `n` may have been checked against a common set of *error* values. + * `n` may have been checked against a common set of *success* values. */ predicate checkedSuccess(Variable v, ControlFlowNode n) { successSuccessor(v, n) From e8dc77d5080a1c5461a570e8fee0188800b56d7d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 15 Apr 2020 14:06:16 +0200 Subject: [PATCH 435/459] add support for util.promisify with child_process calls --- .../semmle/javascript/frameworks/NodeJSLib.qll | 8 ++++++++ .../Security/CWE-078/CommandInjection.expected | 16 ++++++++++++++++ .../Security/CWE-078/child_process-test.js | 9 +++++++++ 3 files changed, 33 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 78393a1aabf..bf343b28603 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -594,6 +594,14 @@ module NodeJSLib { ChildProcessMethodCall() { this = DataFlow::moduleMember("child_process", methodName).getACall() + or + exists(DataFlow::CallNode promisify | + promisify = DataFlow::moduleMember("util", "promisify").getACall() + | + this = promisify.getACall() and + promisify.getArgument(0).getALocalSource() = + DataFlow::moduleMember("child_process", methodName) + ) } private DataFlow::Node getACommandArgument(boolean shell) { diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 589deda96c9..caffc921a77 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -39,6 +39,14 @@ nodes | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | | child_process-test.js:54:46:54:48 | cmd | +| child_process-test.js:70:9:70:49 | cmd | +| child_process-test.js:70:15:70:38 | url.par ... , true) | +| child_process-test.js:70:15:70:44 | url.par ... ).query | +| child_process-test.js:70:15:70:49 | url.par ... ry.path | +| child_process-test.js:70:25:70:31 | req.url | +| child_process-test.js:70:25:70:31 | req.url | +| child_process-test.js:72:29:72:31 | cmd | +| child_process-test.js:72:29:72:31 | cmd | | execSeries.js:3:20:3:22 | arr | | execSeries.js:6:14:6:16 | arr | | execSeries.js:6:14:6:21 | arr[i++] | @@ -129,6 +137,13 @@ edges | child_process-test.js:53:54:53:56 | cmd | child_process-test.js:53:46:53:57 | ["bar", cmd] | | child_process-test.js:54:46:54:48 | cmd | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | | child_process-test.js:54:46:54:48 | cmd | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | +| child_process-test.js:70:9:70:49 | cmd | child_process-test.js:72:29:72:31 | cmd | +| child_process-test.js:70:9:70:49 | cmd | child_process-test.js:72:29:72:31 | cmd | +| child_process-test.js:70:15:70:38 | url.par ... , true) | child_process-test.js:70:15:70:44 | url.par ... ).query | +| child_process-test.js:70:15:70:44 | url.par ... ).query | child_process-test.js:70:15:70:49 | url.par ... ry.path | +| child_process-test.js:70:15:70:49 | url.par ... ry.path | child_process-test.js:70:9:70:49 | cmd | +| child_process-test.js:70:25:70:31 | req.url | child_process-test.js:70:15:70:38 | url.par ... , true) | +| child_process-test.js:70:25:70:31 | req.url | child_process-test.js:70:15:70:38 | url.par ... , true) | | execSeries.js:3:20:3:22 | arr | execSeries.js:6:14:6:16 | arr | | execSeries.js:6:14:6:16 | arr | execSeries.js:6:14:6:21 | arr[i++] | | execSeries.js:6:14:6:21 | arr[i++] | execSeries.js:14:24:14:30 | command | @@ -197,6 +212,7 @@ edges | child_process-test.js:54:5:54:50 | cp.spaw ... t(cmd)) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | | child_process-test.js:59:5:59:39 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:50:15:50:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | | child_process-test.js:64:3:64:21 | cp.spawn(cmd, args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:72:29:72:31 | cmd | child_process-test.js:70:25:70:31 | req.url | child_process-test.js:72:29:72:31 | cmd | This command depends on $@. | child_process-test.js:70:25:70:31 | req.url | a user-provided value | | execSeries.js:14:41:14:47 | command | execSeries.js:18:34:18:40 | req.url | execSeries.js:14:41:14:47 | command | This command depends on $@. | execSeries.js:18:34:18:40 | req.url | a user-provided value | | other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | | other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js b/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js index c9ece717eb0..c85b4907a3b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js @@ -63,3 +63,12 @@ var server = http.createServer(function(req, res) { function run(cmd, args) { cp.spawn(cmd, args); // NOT OK } + +var util = require("util") + +http.createServer(function(req, res) { + let cmd = url.parse(req.url, true).query.path; + + util.promisify(cp.exec)(cmd); // NOT OK +}); + From 90dc14c56ef285ca682dbef778f14dd0090de0a6 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Wed, 15 Apr 2020 18:24:11 -0400 Subject: [PATCH 436/459] C++/C#: Fix phantom `Chi` definitions in `PrintSSA` When `PrintSSA.qll` is imported, IR dumps will be annotated with the alias analysis information used during SSA construction. When printing this information, we incorrectly treated instructions at offset -1, which should only be `Phi` instructions, as `Chi` instructions for the instruction at offset 0. This produced phantom annotations, but did not affect the correctness of the actual IR. --- .../cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll | 3 ++- .../cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll | 3 ++- .../ir/implementation/unaliased_ssa/internal/PrintSSA.qll | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll index dc02760c7c4..72bb239c153 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll @@ -6,11 +6,12 @@ private import DebugSSA bindingset[offset] private string getKeySuffixForOffset(int offset) { + offset >= 0 and if offset % 2 = 0 then result = "" else result = "_Chi" } bindingset[offset] -private int getIndexForOffset(int offset) { result = offset / 2 } +private int getIndexForOffset(int offset) { offset >= 0 and result = offset / 2 } /** * Property provide that dumps the memory access of each result. Useful for debugging SSA diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll index dc02760c7c4..72bb239c153 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll @@ -6,11 +6,12 @@ private import DebugSSA bindingset[offset] private string getKeySuffixForOffset(int offset) { + offset >= 0 and if offset % 2 = 0 then result = "" else result = "_Chi" } bindingset[offset] -private int getIndexForOffset(int offset) { result = offset / 2 } +private int getIndexForOffset(int offset) { offset >= 0 and result = offset / 2 } /** * Property provide that dumps the memory access of each result. Useful for debugging SSA diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll index dc02760c7c4..72bb239c153 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll @@ -6,11 +6,12 @@ private import DebugSSA bindingset[offset] private string getKeySuffixForOffset(int offset) { + offset >= 0 and if offset % 2 = 0 then result = "" else result = "_Chi" } bindingset[offset] -private int getIndexForOffset(int offset) { result = offset / 2 } +private int getIndexForOffset(int offset) { offset >= 0 and result = offset / 2 } /** * Property provide that dumps the memory access of each result. Useful for debugging SSA From 2264ec714f1339102cd968718ad55906efb3e3e4 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Wed, 15 Apr 2020 18:41:24 -0400 Subject: [PATCH 437/459] C++: Better type preservation in `getVariableType()` `getVariableType()` is used to compute the actual semantic type of a variable from its declared type. That's where we handle pointer and function decay for parameters, and it's also where we handle arrays of unknown bound initialized with an initializer of known bound. Previously, even if neither of the above situations applied, the type that we returned was the `getUnspecifiedType()` of the variable. This meant that, for example, `const char* p` would be treated as `char *`. This is inconsistent with how we handle types elsewhere in IR construction, where we preserve typedefs and cv-qualifiers when creating the `CppType` of an `IRVariable`, `Instruction`, or `Operand`. The only visible effect this fix has is to fix the inferred result type for `Phi` instructions for variables affect by this change in `getVariableType()` behavior. Previously, we would see the variable accessed as both `const char*` and as `char*`, so we'd fall back to the canonical pointer type, which is `decltype(nullptr)`. Now, we see the same type for all accesses to the variable, so we use that type as the type of the SSA memory location and as the result type of the `Phi` instruction. --- .../code/cpp/ir/internal/IRUtilities.qll | 11 ++++++---- .../GlobalValueNumbering/ir_gvn.expected | 22 +++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll index 53c15663796..6b2b4c918af 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll @@ -23,17 +23,20 @@ Type getVariableType(Variable v) { then result = getDecayedType(declaredType) or - not exists(getDecayedType(declaredType)) and result = declaredType + not exists(getDecayedType(declaredType)) and result = v.getType() else if declaredType instanceof ArrayType and not declaredType.(ArrayType).hasArraySize() then - result = v.getInitializer().getExpr().getUnspecifiedType() + result = v.getInitializer().getExpr().getType() or - not exists(v.getInitializer()) and result = declaredType - else result = declaredType + not exists(v.getInitializer()) and result = v.getType() + else result = v.getType() ) } +/** + * Holds if the database contains a `case` label with the specified minimum and maximum value. + */ predicate hasCaseEdge(SwitchCase switchCase, string minValue, string maxValue) { minValue = switchCase.getExpr().getFullyConverted().getValue() and if exists(switchCase.getEndExpr()) diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index a492fb47d41..fd6f221c0e8 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -433,27 +433,27 @@ test.cpp: #-----| Goto -> Block 3 # 56| Block 3 -# 56| m56_1(decltype(nullptr)) = Phi : from 2:m55_4, from 5:m56_23 +# 56| m56_1(char *) = Phi : from 2:m55_4, from 5:m56_23 # 56| valnum = m56_1, r56_13, r56_20, r56_3, r59_2 -# 56| r56_2(glval) = VariableAddress[ptr] : +# 56| r56_2(glval) = VariableAddress[ptr] : # 56| valnum = r50_1, r55_3, r56_12, r56_19, r56_2, r59_1 -# 56| r56_3(char *) = Load : &:r56_2, m56_1 +# 56| r56_3(char *) = Load : &:r56_2, m56_1 # 56| valnum = m56_1, r56_13, r56_20, r56_3, r59_2 -# 56| r56_4(char) = Load : &:r56_3, ~m49_4 +# 56| r56_4(char) = Load : &:r56_3, ~m49_4 # 56| valnum = r56_14, r56_4, r59_3 -# 56| r56_5(int) = Convert : r56_4 +# 56| r56_5(int) = Convert : r56_4 # 56| valnum = r56_15, r56_5, r59_4 -# 56| r56_6(glval) = VariableAddress[str] : +# 56| r56_6(glval) = VariableAddress[str] : # 56| valnum = r49_6, r53_2, r56_6 -# 56| r56_7(char *) = Load : &:r56_6, m49_7 +# 56| r56_7(char *) = Load : &:r56_6, m49_7 # 56| valnum = m49_7, r49_8, r53_3, r56_7 -# 56| r56_8(char) = Load : &:r56_7, ~m49_9 +# 56| r56_8(char) = Load : &:r56_7, ~m49_9 # 56| valnum = r53_4, r56_8 -# 56| r56_9(int) = Convert : r56_8 +# 56| r56_9(int) = Convert : r56_8 # 56| valnum = r53_5, r56_9 -# 56| r56_10(bool) = CompareNE : r56_5, r56_9 +# 56| r56_10(bool) = CompareNE : r56_5, r56_9 # 56| valnum = unique -# 56| v56_11(void) = ConditionalBranch : r56_10 +# 56| v56_11(void) = ConditionalBranch : r56_10 #-----| False -> Block 6 #-----| True -> Block 4 From 62e2ffe62346a01a4bf63eca9d0b747919f7738f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 16 Apr 2020 17:19:12 +0200 Subject: [PATCH 438/459] C++: Make PartialDefinitionNode private and add/update comments based on review comments --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 18 ++++++++++++++++-- .../dataflow/taint-tests/taint.cpp | 16 ++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index c5c994a8509..8b0ade838dd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -251,7 +251,7 @@ abstract class PostUpdateNode extends InstructionNode { * setY(&x); // a partial definition of the object `x`. * ``` */ -abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { } +abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { } private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { override ChiInstruction instr; @@ -264,7 +264,7 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { } // There might be multiple `ChiInstructions` that has a particular instruction as - // the total operand - so this definition give consistency errors in + // the total operand - so this definition gives consistency errors in // DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications // this consistency failure has. override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } @@ -430,9 +430,23 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // for now. iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or + // The next two rules allow flow from partial definitions in setters to succeeding loads in the caller. + // First, we add flow from write side-effects to non-conflated chi instructions through their + // partial operands. Consider the following example: + // ``` + // void setX(Point* p, int new_x) { + // p->x = new_x; + // } + // ... + // setX(&p, taint()); + // ``` + // Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to + // `setX`, which will be melded into `p` through a chi instruction. iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and not iTo.isResultConflated() or + // Next, we add flow from non-conflated chi instructions to loads (even when they are not precise). + // This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above. exists(ChiInstruction chi | iFrom = chi | not chi.isResultConflated() and iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index efcd600e21e..5d8327017fa 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -85,14 +85,14 @@ void class_field_test() { mc1.myMethod(); - sink(mc1.a); // [FALSE POSITIVE] - sink(mc1.b); // tainted - sink(mc1.c); // tainted - sink(mc1.d); // tainted - sink(mc2.a); // [FALSE POSITIVE] - sink(mc2.b); // tainted - sink(mc2.c); // tainted - sink(mc2.d); // [FALSE POSITIVE] + sink(mc1.a); + sink(mc1.b); // tainted [NOT DETECTED with IR] + sink(mc1.c); // tainted [NOT DETECTED with IR] + sink(mc1.d); // tainted [NOT DETECTED with IR] + sink(mc2.a); + sink(mc2.b); // tainted [NOT DETECTED with IR] + sink(mc2.c); // tainted [NOT DETECTED with IR] + sink(mc2.d); } // --- arrays --- From c705797a2dede130fd4fb83660f1d1c1b2908216 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Thu, 16 Apr 2020 11:58:09 -0400 Subject: [PATCH 439/459] C++: IR construction for `_Imaginary` types Includes a fairly exhaustive test case for arithmetic operations involving `_Complex` and/or `_Imaginary` types. Thanks to these new tests, I discovered that the extractor treats certain arithmetic operations on `_Imaginary` types as separate expression kinds, so I added support for those kinds in IR construction. --- .../raw/internal/TranslatedExpr.qll | 31 +- .../library-tests/ir/ir/PrintAST.expected | 1503 ++++++++++++++++- cpp/ql/test/library-tests/ir/ir/complex.c | 150 +- .../test/library-tests/ir/ir/raw_ir.expected | 601 ++++++- cpp/ql/test/library-tests/ir/types/complex.c | 13 +- 5 files changed, 2219 insertions(+), 79 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index b8ede454ba2..c072aae1258 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -1100,13 +1100,36 @@ private Opcode binaryBitwiseOpcode(BinaryBitwiseOperation expr) { } private Opcode binaryArithmeticOpcode(BinaryArithmeticOperation expr) { - expr instanceof AddExpr and result instanceof Opcode::Add + ( + expr instanceof AddExpr + or + expr instanceof ImaginaryRealAddExpr + or + expr instanceof RealImaginaryAddExpr + ) and + result instanceof Opcode::Add or - expr instanceof SubExpr and result instanceof Opcode::Sub + ( + expr instanceof SubExpr + or + expr instanceof ImaginaryRealSubExpr + or + expr instanceof RealImaginarySubExpr + ) and + result instanceof Opcode::Sub or - expr instanceof MulExpr and result instanceof Opcode::Mul + ( + expr instanceof MulExpr + or + expr instanceof ImaginaryMulExpr + ) and + result instanceof Opcode::Mul or - expr instanceof DivExpr and result instanceof Opcode::Div + ( + expr instanceof DivExpr or + expr instanceof ImaginaryDivExpr + ) and + result instanceof Opcode::Div or expr instanceof RemExpr and result instanceof Opcode::Rem or diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 2ff49047c8d..24b09161af3 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -235,7 +235,7 @@ clang.cpp: # 6| Type = [IntType] int # 6| ValueCategory = lvalue complex.c: -# 1| [TopLevelFunction] void complex_math() +# 1| [TopLevelFunction] void complex_literals() # 1| params: # 1| body: [Block] { ... } # 2| 0: [DeclStmt] declaration @@ -246,50 +246,1475 @@ complex.c: # 2| Conversion = [FloatingPointConversion] floating point conversion # 2| Type = [ArithmeticType] _Complex float # 2| ValueCategory = prvalue -# 2| expr: [AddExpr] ... + ... -# 2| Type = [ArithmeticType] _Complex double +# 2| expr: [Literal] 2.0 +# 2| Type = [DoubleType] double +# 2| Value = [Literal] 2.0 # 2| ValueCategory = prvalue -# 2| 0: [CStyleCast] (_Complex double)... -# 2| Conversion = [FloatingPointConversion] floating point conversion -# 2| Type = [ArithmeticType] _Complex double -# 2| ValueCategory = prvalue -# 2| expr: [Literal] 2.0 -# 2| Type = [DoubleType] double -# 2| Value = [Literal] 2.0 -# 2| ValueCategory = prvalue -# 2| 1: [CStyleCast] (_Complex double)... -# 2| Conversion = [FloatingPointConversion] floating point conversion -# 2| Type = [ArithmeticType] _Complex double -# 2| ValueCategory = prvalue -# 2| expr: [Literal] (0.0,1.0i) -# 2| Type = [ArithmeticType] _Complex float -# 2| Value = [Literal] (0.0,1.0i) -# 2| ValueCategory = prvalue -# 3| 1: [DeclStmt] declaration -# 3| 0: [VariableDeclarationEntry] definition of cf2 +# 3| 1: [ExprStmt] ExprStmt +# 3| 0: [AssignExpr] ... = ... # 3| Type = [ArithmeticType] _Complex float -# 3| init: [Initializer] initializer for cf2 -# 3| expr: [MulExpr] ... * ... -# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = prvalue +# 3| 0: [VariableAccess] cf +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = lvalue +# 3| 1: [CStyleCast] (_Complex float)... +# 3| Conversion = [FloatingPointConversion] floating point conversion +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = prvalue +# 3| expr: [Literal] 1.0i +# 3| Type = [ArithmeticType] _Imaginary float +# 3| Value = [Literal] 1.0i # 3| ValueCategory = prvalue -# 3| 0: [VariableAccess] cf -# 3| Type = [ArithmeticType] _Complex float -# 3| ValueCategory = prvalue(load) -# 3| 1: [VariableAccess] cf -# 3| Type = [ArithmeticType] _Complex float -# 3| ValueCategory = prvalue(load) # 4| 2: [DeclStmt] declaration -# 4| 0: [VariableDeclarationEntry] definition of d -# 4| Type = [DoubleType] double -# 4| init: [Initializer] initializer for d -# 4| expr: [CStyleCast] (double)... +# 4| 0: [VariableDeclarationEntry] definition of cd +# 4| Type = [ArithmeticType] _Complex double +# 4| init: [Initializer] initializer for cd +# 4| expr: [CStyleCast] (_Complex double)... # 4| Conversion = [FloatingPointConversion] floating point conversion -# 4| Type = [DoubleType] double +# 4| Type = [ArithmeticType] _Complex double # 4| ValueCategory = prvalue -# 4| expr: [VariableAccess] cf2 -# 4| Type = [ArithmeticType] _Complex float -# 4| ValueCategory = prvalue(load) -# 5| 3: [ReturnStmt] return ... +# 4| expr: [Literal] 3.0 +# 4| Type = [DoubleType] double +# 4| Value = [Literal] 3.0 +# 4| ValueCategory = prvalue +# 5| 3: [ExprStmt] ExprStmt +# 5| 0: [AssignExpr] ... = ... +# 5| Type = [ArithmeticType] _Complex double +# 5| ValueCategory = prvalue +# 5| 0: [VariableAccess] cd +# 5| Type = [ArithmeticType] _Complex double +# 5| ValueCategory = lvalue +# 5| 1: [CStyleCast] (_Complex double)... +# 5| Conversion = [FloatingPointConversion] floating point conversion +# 5| Type = [ArithmeticType] _Complex double +# 5| ValueCategory = prvalue +# 5| expr: [Literal] 1.0i +# 5| Type = [ArithmeticType] _Imaginary float +# 5| Value = [Literal] 1.0i +# 5| ValueCategory = prvalue +# 6| 4: [DeclStmt] declaration +# 6| 0: [VariableDeclarationEntry] definition of cld +# 6| Type = [ArithmeticType] _Complex long double +# 6| init: [Initializer] initializer for cld +# 6| expr: [CStyleCast] (_Complex long double)... +# 6| Conversion = [FloatingPointConversion] floating point conversion +# 6| Type = [ArithmeticType] _Complex long double +# 6| ValueCategory = prvalue +# 6| expr: [Literal] 5.0 +# 6| Type = [DoubleType] double +# 6| Value = [Literal] 5.0 +# 6| ValueCategory = prvalue +# 7| 5: [ExprStmt] ExprStmt +# 7| 0: [AssignExpr] ... = ... +# 7| Type = [ArithmeticType] _Complex long double +# 7| ValueCategory = prvalue +# 7| 0: [VariableAccess] cld +# 7| Type = [ArithmeticType] _Complex long double +# 7| ValueCategory = lvalue +# 7| 1: [CStyleCast] (_Complex long double)... +# 7| Conversion = [FloatingPointConversion] floating point conversion +# 7| Type = [ArithmeticType] _Complex long double +# 7| ValueCategory = prvalue +# 7| expr: [Literal] 1.0i +# 7| Type = [ArithmeticType] _Imaginary float +# 7| Value = [Literal] 1.0i +# 7| ValueCategory = prvalue +# 9| 6: [DeclStmt] declaration +# 9| 0: [VariableDeclarationEntry] definition of jf +# 9| Type = [ArithmeticType] _Imaginary float +# 9| init: [Initializer] initializer for jf +# 9| expr: [Literal] 1.0i +# 9| Type = [ArithmeticType] _Imaginary float +# 9| Value = [Literal] 1.0i +# 9| ValueCategory = prvalue +# 10| 7: [DeclStmt] declaration +# 10| 0: [VariableDeclarationEntry] definition of jd +# 10| Type = [ArithmeticType] _Imaginary double +# 10| init: [Initializer] initializer for jd +# 10| expr: [CStyleCast] (_Imaginary double)... +# 10| Conversion = [FloatingPointConversion] floating point conversion +# 10| Type = [ArithmeticType] _Imaginary double +# 10| ValueCategory = prvalue +# 10| expr: [Literal] 1.0i +# 10| Type = [ArithmeticType] _Imaginary float +# 10| Value = [Literal] 1.0i +# 10| ValueCategory = prvalue +# 11| 8: [DeclStmt] declaration +# 11| 0: [VariableDeclarationEntry] definition of jld +# 11| Type = [ArithmeticType] _Imaginary long double +# 11| init: [Initializer] initializer for jld +# 11| expr: [CStyleCast] (_Imaginary long double)... +# 11| Conversion = [FloatingPointConversion] floating point conversion +# 11| Type = [ArithmeticType] _Imaginary long double +# 11| ValueCategory = prvalue +# 11| expr: [Literal] 1.0i +# 11| Type = [ArithmeticType] _Imaginary float +# 11| Value = [Literal] 1.0i +# 11| ValueCategory = prvalue +# 12| 9: [ReturnStmt] return ... +# 14| [TopLevelFunction] void complex_arithmetic() +# 14| params: +# 14| body: [Block] { ... } +# 15| 0: [DeclStmt] declaration +# 15| 0: [VariableDeclarationEntry] definition of f1 +# 15| Type = [FloatType] float +# 15| init: [Initializer] initializer for f1 +# 15| expr: [CStyleCast] (float)... +# 15| Conversion = [FloatingPointConversion] floating point conversion +# 15| Type = [FloatType] float +# 15| Value = [CStyleCast] 5.0 +# 15| ValueCategory = prvalue +# 15| expr: [Literal] 5.0 +# 15| Type = [DoubleType] double +# 15| Value = [Literal] 5.0 +# 15| ValueCategory = prvalue +# 16| 1: [DeclStmt] declaration +# 16| 0: [VariableDeclarationEntry] definition of f2 +# 16| Type = [FloatType] float +# 16| init: [Initializer] initializer for f2 +# 16| expr: [CStyleCast] (float)... +# 16| Conversion = [FloatingPointConversion] floating point conversion +# 16| Type = [FloatType] float +# 16| Value = [CStyleCast] 7.0 +# 16| ValueCategory = prvalue +# 16| expr: [Literal] 7.0 +# 16| Type = [DoubleType] double +# 16| Value = [Literal] 7.0 +# 16| ValueCategory = prvalue +# 17| 2: [DeclStmt] declaration +# 17| 0: [VariableDeclarationEntry] definition of f3 +# 17| Type = [FloatType] float +# 18| 3: [DeclStmt] declaration +# 18| 0: [VariableDeclarationEntry] definition of cf1 +# 18| Type = [ArithmeticType] _Complex float +# 18| init: [Initializer] initializer for cf1 +# 18| expr: [CStyleCast] (_Complex float)... +# 18| Conversion = [FloatingPointConversion] floating point conversion +# 18| Type = [ArithmeticType] _Complex float +# 18| ValueCategory = prvalue +# 18| expr: [Literal] 2.0 +# 18| Type = [DoubleType] double +# 18| Value = [Literal] 2.0 +# 18| ValueCategory = prvalue +# 19| 4: [DeclStmt] declaration +# 19| 0: [VariableDeclarationEntry] definition of cf2 +# 19| Type = [ArithmeticType] _Complex float +# 19| init: [Initializer] initializer for cf2 +# 19| expr: [CStyleCast] (_Complex float)... +# 19| Conversion = [FloatingPointConversion] floating point conversion +# 19| Type = [ArithmeticType] _Complex float +# 19| ValueCategory = prvalue +# 19| expr: [Literal] 1.0i +# 19| Type = [ArithmeticType] _Imaginary float +# 19| Value = [Literal] 1.0i +# 19| ValueCategory = prvalue +# 20| 5: [DeclStmt] declaration +# 20| 0: [VariableDeclarationEntry] definition of cf3 +# 20| Type = [ArithmeticType] _Complex float +# 21| 6: [DeclStmt] declaration +# 21| 0: [VariableDeclarationEntry] definition of jf1 +# 21| Type = [ArithmeticType] _Imaginary float +# 21| init: [Initializer] initializer for jf1 +# 21| expr: [Literal] 1.0i +# 21| Type = [ArithmeticType] _Imaginary float +# 21| Value = [Literal] 1.0i +# 21| ValueCategory = prvalue +# 22| 7: [DeclStmt] declaration +# 22| 0: [VariableDeclarationEntry] definition of jf2 +# 22| Type = [ArithmeticType] _Imaginary float +# 22| init: [Initializer] initializer for jf2 +# 22| expr: [Literal] 1.0i +# 22| Type = [ArithmeticType] _Imaginary float +# 22| Value = [Literal] 1.0i +# 22| ValueCategory = prvalue +# 23| 8: [DeclStmt] declaration +# 23| 0: [VariableDeclarationEntry] definition of jf3 +# 23| Type = [ArithmeticType] _Imaginary float +# 26| 9: [ExprStmt] ExprStmt +# 26| 0: [AssignExpr] ... = ... +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = prvalue +# 26| 0: [VariableAccess] cf3 +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = lvalue +# 26| 1: [UnaryPlusExpr] + ... +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = prvalue +# 26| 0: [VariableAccess] cf1 +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = prvalue(load) +# 27| 10: [ExprStmt] ExprStmt +# 27| 0: [AssignExpr] ... = ... +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = prvalue +# 27| 0: [VariableAccess] cf3 +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = lvalue +# 27| 1: [UnaryMinusExpr] - ... +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = prvalue +# 27| 0: [VariableAccess] cf1 +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = prvalue(load) +# 30| 11: [ExprStmt] ExprStmt +# 30| 0: [AssignExpr] ... = ... +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue +# 30| 0: [VariableAccess] cf3 +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = lvalue +# 30| 1: [AddExpr] ... + ... +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue +# 30| 0: [VariableAccess] cf1 +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue(load) +# 30| 1: [VariableAccess] cf2 +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue(load) +# 31| 12: [ExprStmt] ExprStmt +# 31| 0: [AssignExpr] ... = ... +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue +# 31| 0: [VariableAccess] cf3 +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = lvalue +# 31| 1: [SubExpr] ... - ... +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue +# 31| 0: [VariableAccess] cf1 +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue(load) +# 31| 1: [VariableAccess] cf2 +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue(load) +# 32| 13: [ExprStmt] ExprStmt +# 32| 0: [AssignExpr] ... = ... +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue +# 32| 0: [VariableAccess] cf3 +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = lvalue +# 32| 1: [MulExpr] ... * ... +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue +# 32| 0: [VariableAccess] cf1 +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue(load) +# 32| 1: [VariableAccess] cf2 +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue(load) +# 33| 14: [ExprStmt] ExprStmt +# 33| 0: [AssignExpr] ... = ... +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue +# 33| 0: [VariableAccess] cf3 +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = lvalue +# 33| 1: [DivExpr] ... / ... +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue +# 33| 0: [VariableAccess] cf1 +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue(load) +# 33| 1: [VariableAccess] cf2 +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue(load) +# 36| 15: [ExprStmt] ExprStmt +# 36| 0: [AssignExpr] ... = ... +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = prvalue +# 36| 0: [VariableAccess] jf3 +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = lvalue +# 36| 1: [UnaryPlusExpr] + ... +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = prvalue +# 36| 0: [VariableAccess] jf1 +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = prvalue(load) +# 37| 16: [ExprStmt] ExprStmt +# 37| 0: [AssignExpr] ... = ... +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = prvalue +# 37| 0: [VariableAccess] jf3 +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = lvalue +# 37| 1: [UnaryMinusExpr] - ... +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = prvalue +# 37| 0: [VariableAccess] jf1 +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = prvalue(load) +# 40| 17: [ExprStmt] ExprStmt +# 40| 0: [AssignExpr] ... = ... +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue +# 40| 0: [VariableAccess] jf3 +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = lvalue +# 40| 1: [AddExpr] ... + ... +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue +# 40| 0: [VariableAccess] jf1 +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue(load) +# 40| 1: [VariableAccess] jf2 +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue(load) +# 41| 18: [ExprStmt] ExprStmt +# 41| 0: [AssignExpr] ... = ... +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue +# 41| 0: [VariableAccess] jf3 +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = lvalue +# 41| 1: [SubExpr] ... - ... +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue +# 41| 0: [VariableAccess] jf1 +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue(load) +# 41| 1: [VariableAccess] jf2 +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue(load) +# 42| 19: [ExprStmt] ExprStmt +# 42| 0: [AssignExpr] ... = ... +# 42| Type = [FloatType] float +# 42| ValueCategory = prvalue +# 42| 0: [VariableAccess] f3 +# 42| Type = [FloatType] float +# 42| ValueCategory = lvalue +# 42| 1: [ImaginaryMulExpr] ... * ... +# 42| Type = [FloatType] float +# 42| ValueCategory = prvalue +# 42| 0: [VariableAccess] jf1 +# 42| Type = [ArithmeticType] _Imaginary float +# 42| ValueCategory = prvalue(load) +# 42| 1: [VariableAccess] jf2 +# 42| Type = [ArithmeticType] _Imaginary float +# 42| ValueCategory = prvalue(load) +# 43| 20: [ExprStmt] ExprStmt +# 43| 0: [AssignExpr] ... = ... +# 43| Type = [FloatType] float +# 43| ValueCategory = prvalue +# 43| 0: [VariableAccess] f3 +# 43| Type = [FloatType] float +# 43| ValueCategory = lvalue +# 43| 1: [DivExpr] ... / ... +# 43| Type = [FloatType] float +# 43| ValueCategory = prvalue +# 43| 0: [VariableAccess] jf1 +# 43| Type = [ArithmeticType] _Imaginary float +# 43| ValueCategory = prvalue(load) +# 43| 1: [VariableAccess] jf2 +# 43| Type = [ArithmeticType] _Imaginary float +# 43| ValueCategory = prvalue(load) +# 46| 21: [ExprStmt] ExprStmt +# 46| 0: [AssignExpr] ... = ... +# 46| Type = [ArithmeticType] _Complex float +# 46| ValueCategory = prvalue +# 46| 0: [VariableAccess] cf3 +# 46| Type = [ArithmeticType] _Complex float +# 46| ValueCategory = lvalue +# 46| 1: [ImaginaryRealAddExpr] ... + ... +# 46| Type = [ArithmeticType] _Complex float +# 46| ValueCategory = prvalue +# 46| 0: [VariableAccess] jf1 +# 46| Type = [ArithmeticType] _Imaginary float +# 46| ValueCategory = prvalue(load) +# 46| 1: [VariableAccess] f2 +# 46| Type = [FloatType] float +# 46| ValueCategory = prvalue(load) +# 47| 22: [ExprStmt] ExprStmt +# 47| 0: [AssignExpr] ... = ... +# 47| Type = [ArithmeticType] _Complex float +# 47| ValueCategory = prvalue +# 47| 0: [VariableAccess] cf3 +# 47| Type = [ArithmeticType] _Complex float +# 47| ValueCategory = lvalue +# 47| 1: [ImaginaryRealSubExpr] ... - ... +# 47| Type = [ArithmeticType] _Complex float +# 47| ValueCategory = prvalue +# 47| 0: [VariableAccess] jf1 +# 47| Type = [ArithmeticType] _Imaginary float +# 47| ValueCategory = prvalue(load) +# 47| 1: [VariableAccess] f2 +# 47| Type = [FloatType] float +# 47| ValueCategory = prvalue(load) +# 48| 23: [ExprStmt] ExprStmt +# 48| 0: [AssignExpr] ... = ... +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = prvalue +# 48| 0: [VariableAccess] jf3 +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = lvalue +# 48| 1: [MulExpr] ... * ... +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = prvalue +# 48| 0: [VariableAccess] jf1 +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = prvalue(load) +# 48| 1: [VariableAccess] f2 +# 48| Type = [FloatType] float +# 48| ValueCategory = prvalue(load) +# 49| 24: [ExprStmt] ExprStmt +# 49| 0: [AssignExpr] ... = ... +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = prvalue +# 49| 0: [VariableAccess] jf3 +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = lvalue +# 49| 1: [DivExpr] ... / ... +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = prvalue +# 49| 0: [VariableAccess] jf1 +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = prvalue(load) +# 49| 1: [VariableAccess] f2 +# 49| Type = [FloatType] float +# 49| ValueCategory = prvalue(load) +# 52| 25: [ExprStmt] ExprStmt +# 52| 0: [AssignExpr] ... = ... +# 52| Type = [ArithmeticType] _Complex float +# 52| ValueCategory = prvalue +# 52| 0: [VariableAccess] cf3 +# 52| Type = [ArithmeticType] _Complex float +# 52| ValueCategory = lvalue +# 52| 1: [RealImaginaryAddExpr] ... + ... +# 52| Type = [ArithmeticType] _Complex float +# 52| ValueCategory = prvalue +# 52| 0: [VariableAccess] f1 +# 52| Type = [FloatType] float +# 52| ValueCategory = prvalue(load) +# 52| 1: [VariableAccess] jf2 +# 52| Type = [ArithmeticType] _Imaginary float +# 52| ValueCategory = prvalue(load) +# 53| 26: [ExprStmt] ExprStmt +# 53| 0: [AssignExpr] ... = ... +# 53| Type = [ArithmeticType] _Complex float +# 53| ValueCategory = prvalue +# 53| 0: [VariableAccess] cf3 +# 53| Type = [ArithmeticType] _Complex float +# 53| ValueCategory = lvalue +# 53| 1: [RealImaginarySubExpr] ... - ... +# 53| Type = [ArithmeticType] _Complex float +# 53| ValueCategory = prvalue +# 53| 0: [VariableAccess] f1 +# 53| Type = [FloatType] float +# 53| ValueCategory = prvalue(load) +# 53| 1: [VariableAccess] jf2 +# 53| Type = [ArithmeticType] _Imaginary float +# 53| ValueCategory = prvalue(load) +# 54| 27: [ExprStmt] ExprStmt +# 54| 0: [AssignExpr] ... = ... +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = prvalue +# 54| 0: [VariableAccess] jf3 +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = lvalue +# 54| 1: [MulExpr] ... * ... +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = prvalue +# 54| 0: [VariableAccess] f1 +# 54| Type = [FloatType] float +# 54| ValueCategory = prvalue(load) +# 54| 1: [VariableAccess] jf2 +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = prvalue(load) +# 55| 28: [ExprStmt] ExprStmt +# 55| 0: [AssignExpr] ... = ... +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = prvalue +# 55| 0: [VariableAccess] jf3 +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = lvalue +# 55| 1: [ImaginaryDivExpr] ... / ... +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = prvalue +# 55| 0: [VariableAccess] f1 +# 55| Type = [FloatType] float +# 55| ValueCategory = prvalue(load) +# 55| 1: [VariableAccess] jf2 +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = prvalue(load) +# 56| 29: [ReturnStmt] return ... +# 58| [TopLevelFunction] void complex_conversions() +# 58| params: +# 58| body: [Block] { ... } +# 59| 0: [DeclStmt] declaration +# 59| 0: [VariableDeclarationEntry] definition of f +# 59| Type = [FloatType] float +# 59| init: [Initializer] initializer for f +# 59| expr: [CStyleCast] (float)... +# 59| Conversion = [FloatingPointConversion] floating point conversion +# 59| Type = [FloatType] float +# 59| Value = [CStyleCast] 2.0 +# 59| ValueCategory = prvalue +# 59| expr: [Literal] 2.0 +# 59| Type = [DoubleType] double +# 59| Value = [Literal] 2.0 +# 59| ValueCategory = prvalue +# 60| 1: [DeclStmt] declaration +# 60| 0: [VariableDeclarationEntry] definition of d +# 60| Type = [DoubleType] double +# 60| init: [Initializer] initializer for d +# 60| expr: [Literal] 3.0 +# 60| Type = [DoubleType] double +# 60| Value = [Literal] 3.0 +# 60| ValueCategory = prvalue +# 61| 2: [DeclStmt] declaration +# 61| 0: [VariableDeclarationEntry] definition of ld +# 61| Type = [LongDoubleType] long double +# 61| init: [Initializer] initializer for ld +# 61| expr: [CStyleCast] (long double)... +# 61| Conversion = [FloatingPointConversion] floating point conversion +# 61| Type = [LongDoubleType] long double +# 61| Value = [CStyleCast] 5.0 +# 61| ValueCategory = prvalue +# 61| expr: [Literal] 5.0 +# 61| Type = [DoubleType] double +# 61| Value = [Literal] 5.0 +# 61| ValueCategory = prvalue +# 62| 3: [DeclStmt] declaration +# 62| 0: [VariableDeclarationEntry] definition of cf +# 62| Type = [ArithmeticType] _Complex float +# 62| init: [Initializer] initializer for cf +# 62| expr: [CStyleCast] (_Complex float)... +# 62| Conversion = [FloatingPointConversion] floating point conversion +# 62| Type = [ArithmeticType] _Complex float +# 62| ValueCategory = prvalue +# 62| expr: [Literal] 7.0 +# 62| Type = [DoubleType] double +# 62| Value = [Literal] 7.0 +# 62| ValueCategory = prvalue +# 63| 4: [DeclStmt] declaration +# 63| 0: [VariableDeclarationEntry] definition of cd +# 63| Type = [ArithmeticType] _Complex double +# 63| init: [Initializer] initializer for cd +# 63| expr: [CStyleCast] (_Complex double)... +# 63| Conversion = [FloatingPointConversion] floating point conversion +# 63| Type = [ArithmeticType] _Complex double +# 63| ValueCategory = prvalue +# 63| expr: [Literal] 11.0 +# 63| Type = [DoubleType] double +# 63| Value = [Literal] 11.0 +# 63| ValueCategory = prvalue +# 64| 5: [DeclStmt] declaration +# 64| 0: [VariableDeclarationEntry] definition of cld +# 64| Type = [ArithmeticType] _Complex long double +# 64| init: [Initializer] initializer for cld +# 64| expr: [CStyleCast] (_Complex long double)... +# 64| Conversion = [FloatingPointConversion] floating point conversion +# 64| Type = [ArithmeticType] _Complex long double +# 64| ValueCategory = prvalue +# 64| expr: [Literal] 13.0 +# 64| Type = [DoubleType] double +# 64| Value = [Literal] 13.0 +# 64| ValueCategory = prvalue +# 65| 6: [DeclStmt] declaration +# 65| 0: [VariableDeclarationEntry] definition of jf +# 65| Type = [ArithmeticType] _Imaginary float +# 65| init: [Initializer] initializer for jf +# 65| expr: [Literal] 1.0i +# 65| Type = [ArithmeticType] _Imaginary float +# 65| Value = [Literal] 1.0i +# 65| ValueCategory = prvalue +# 66| 7: [DeclStmt] declaration +# 66| 0: [VariableDeclarationEntry] definition of jd +# 66| Type = [ArithmeticType] _Imaginary double +# 66| init: [Initializer] initializer for jd +# 66| expr: [CStyleCast] (_Imaginary double)... +# 66| Conversion = [FloatingPointConversion] floating point conversion +# 66| Type = [ArithmeticType] _Imaginary double +# 66| ValueCategory = prvalue +# 66| expr: [Literal] 1.0i +# 66| Type = [ArithmeticType] _Imaginary float +# 66| Value = [Literal] 1.0i +# 66| ValueCategory = prvalue +# 67| 8: [DeclStmt] declaration +# 67| 0: [VariableDeclarationEntry] definition of jld +# 67| Type = [ArithmeticType] _Imaginary long double +# 67| init: [Initializer] initializer for jld +# 67| expr: [CStyleCast] (_Imaginary long double)... +# 67| Conversion = [FloatingPointConversion] floating point conversion +# 67| Type = [ArithmeticType] _Imaginary long double +# 67| ValueCategory = prvalue +# 67| expr: [Literal] 1.0i +# 67| Type = [ArithmeticType] _Imaginary float +# 67| Value = [Literal] 1.0i +# 67| ValueCategory = prvalue +# 70| 9: [ExprStmt] ExprStmt +# 70| 0: [AssignExpr] ... = ... +# 70| Type = [ArithmeticType] _Complex float +# 70| ValueCategory = prvalue +# 70| 0: [VariableAccess] cf +# 70| Type = [ArithmeticType] _Complex float +# 70| ValueCategory = lvalue +# 70| 1: [VariableAccess] cf +# 70| Type = [ArithmeticType] _Complex float +# 70| ValueCategory = prvalue(load) +# 71| 10: [ExprStmt] ExprStmt +# 71| 0: [AssignExpr] ... = ... +# 71| Type = [ArithmeticType] _Complex float +# 71| ValueCategory = prvalue +# 71| 0: [VariableAccess] cf +# 71| Type = [ArithmeticType] _Complex float +# 71| ValueCategory = lvalue +# 71| 1: [CStyleCast] (_Complex float)... +# 71| Conversion = [FloatingPointConversion] floating point conversion +# 71| Type = [ArithmeticType] _Complex float +# 71| ValueCategory = prvalue +# 71| expr: [VariableAccess] cd +# 71| Type = [ArithmeticType] _Complex double +# 71| ValueCategory = prvalue(load) +# 72| 11: [ExprStmt] ExprStmt +# 72| 0: [AssignExpr] ... = ... +# 72| Type = [ArithmeticType] _Complex float +# 72| ValueCategory = prvalue +# 72| 0: [VariableAccess] cf +# 72| Type = [ArithmeticType] _Complex float +# 72| ValueCategory = lvalue +# 72| 1: [CStyleCast] (_Complex float)... +# 72| Conversion = [FloatingPointConversion] floating point conversion +# 72| Type = [ArithmeticType] _Complex float +# 72| ValueCategory = prvalue +# 72| expr: [VariableAccess] cld +# 72| Type = [ArithmeticType] _Complex long double +# 72| ValueCategory = prvalue(load) +# 73| 12: [ExprStmt] ExprStmt +# 73| 0: [AssignExpr] ... = ... +# 73| Type = [ArithmeticType] _Complex double +# 73| ValueCategory = prvalue +# 73| 0: [VariableAccess] cd +# 73| Type = [ArithmeticType] _Complex double +# 73| ValueCategory = lvalue +# 73| 1: [CStyleCast] (_Complex double)... +# 73| Conversion = [FloatingPointConversion] floating point conversion +# 73| Type = [ArithmeticType] _Complex double +# 73| ValueCategory = prvalue +# 73| expr: [VariableAccess] cf +# 73| Type = [ArithmeticType] _Complex float +# 73| ValueCategory = prvalue(load) +# 74| 13: [ExprStmt] ExprStmt +# 74| 0: [AssignExpr] ... = ... +# 74| Type = [ArithmeticType] _Complex double +# 74| ValueCategory = prvalue +# 74| 0: [VariableAccess] cd +# 74| Type = [ArithmeticType] _Complex double +# 74| ValueCategory = lvalue +# 74| 1: [VariableAccess] cd +# 74| Type = [ArithmeticType] _Complex double +# 74| ValueCategory = prvalue(load) +# 75| 14: [ExprStmt] ExprStmt +# 75| 0: [AssignExpr] ... = ... +# 75| Type = [ArithmeticType] _Complex double +# 75| ValueCategory = prvalue +# 75| 0: [VariableAccess] cd +# 75| Type = [ArithmeticType] _Complex double +# 75| ValueCategory = lvalue +# 75| 1: [CStyleCast] (_Complex double)... +# 75| Conversion = [FloatingPointConversion] floating point conversion +# 75| Type = [ArithmeticType] _Complex double +# 75| ValueCategory = prvalue +# 75| expr: [VariableAccess] cld +# 75| Type = [ArithmeticType] _Complex long double +# 75| ValueCategory = prvalue(load) +# 76| 15: [ExprStmt] ExprStmt +# 76| 0: [AssignExpr] ... = ... +# 76| Type = [ArithmeticType] _Complex long double +# 76| ValueCategory = prvalue +# 76| 0: [VariableAccess] cld +# 76| Type = [ArithmeticType] _Complex long double +# 76| ValueCategory = lvalue +# 76| 1: [CStyleCast] (_Complex long double)... +# 76| Conversion = [FloatingPointConversion] floating point conversion +# 76| Type = [ArithmeticType] _Complex long double +# 76| ValueCategory = prvalue +# 76| expr: [VariableAccess] cf +# 76| Type = [ArithmeticType] _Complex float +# 76| ValueCategory = prvalue(load) +# 77| 16: [ExprStmt] ExprStmt +# 77| 0: [AssignExpr] ... = ... +# 77| Type = [ArithmeticType] _Complex long double +# 77| ValueCategory = prvalue +# 77| 0: [VariableAccess] cld +# 77| Type = [ArithmeticType] _Complex long double +# 77| ValueCategory = lvalue +# 77| 1: [CStyleCast] (_Complex long double)... +# 77| Conversion = [FloatingPointConversion] floating point conversion +# 77| Type = [ArithmeticType] _Complex long double +# 77| ValueCategory = prvalue +# 77| expr: [VariableAccess] cd +# 77| Type = [ArithmeticType] _Complex double +# 77| ValueCategory = prvalue(load) +# 78| 17: [ExprStmt] ExprStmt +# 78| 0: [AssignExpr] ... = ... +# 78| Type = [ArithmeticType] _Complex long double +# 78| ValueCategory = prvalue +# 78| 0: [VariableAccess] cld +# 78| Type = [ArithmeticType] _Complex long double +# 78| ValueCategory = lvalue +# 78| 1: [VariableAccess] cld +# 78| Type = [ArithmeticType] _Complex long double +# 78| ValueCategory = prvalue(load) +# 81| 18: [ExprStmt] ExprStmt +# 81| 0: [AssignExpr] ... = ... +# 81| Type = [ArithmeticType] _Complex float +# 81| ValueCategory = prvalue +# 81| 0: [VariableAccess] cf +# 81| Type = [ArithmeticType] _Complex float +# 81| ValueCategory = lvalue +# 81| 1: [CStyleCast] (_Complex float)... +# 81| Conversion = [FloatingPointConversion] floating point conversion +# 81| Type = [ArithmeticType] _Complex float +# 81| ValueCategory = prvalue +# 81| expr: [VariableAccess] f +# 81| Type = [FloatType] float +# 81| ValueCategory = prvalue(load) +# 82| 19: [ExprStmt] ExprStmt +# 82| 0: [AssignExpr] ... = ... +# 82| Type = [ArithmeticType] _Complex float +# 82| ValueCategory = prvalue +# 82| 0: [VariableAccess] cf +# 82| Type = [ArithmeticType] _Complex float +# 82| ValueCategory = lvalue +# 82| 1: [CStyleCast] (_Complex float)... +# 82| Conversion = [FloatingPointConversion] floating point conversion +# 82| Type = [ArithmeticType] _Complex float +# 82| ValueCategory = prvalue +# 82| expr: [VariableAccess] d +# 82| Type = [DoubleType] double +# 82| ValueCategory = prvalue(load) +# 83| 20: [ExprStmt] ExprStmt +# 83| 0: [AssignExpr] ... = ... +# 83| Type = [ArithmeticType] _Complex float +# 83| ValueCategory = prvalue +# 83| 0: [VariableAccess] cf +# 83| Type = [ArithmeticType] _Complex float +# 83| ValueCategory = lvalue +# 83| 1: [CStyleCast] (_Complex float)... +# 83| Conversion = [FloatingPointConversion] floating point conversion +# 83| Type = [ArithmeticType] _Complex float +# 83| ValueCategory = prvalue +# 83| expr: [VariableAccess] ld +# 83| Type = [LongDoubleType] long double +# 83| ValueCategory = prvalue(load) +# 84| 21: [ExprStmt] ExprStmt +# 84| 0: [AssignExpr] ... = ... +# 84| Type = [ArithmeticType] _Complex double +# 84| ValueCategory = prvalue +# 84| 0: [VariableAccess] cd +# 84| Type = [ArithmeticType] _Complex double +# 84| ValueCategory = lvalue +# 84| 1: [CStyleCast] (_Complex double)... +# 84| Conversion = [FloatingPointConversion] floating point conversion +# 84| Type = [ArithmeticType] _Complex double +# 84| ValueCategory = prvalue +# 84| expr: [VariableAccess] f +# 84| Type = [FloatType] float +# 84| ValueCategory = prvalue(load) +# 85| 22: [ExprStmt] ExprStmt +# 85| 0: [AssignExpr] ... = ... +# 85| Type = [ArithmeticType] _Complex double +# 85| ValueCategory = prvalue +# 85| 0: [VariableAccess] cd +# 85| Type = [ArithmeticType] _Complex double +# 85| ValueCategory = lvalue +# 85| 1: [CStyleCast] (_Complex double)... +# 85| Conversion = [FloatingPointConversion] floating point conversion +# 85| Type = [ArithmeticType] _Complex double +# 85| ValueCategory = prvalue +# 85| expr: [VariableAccess] d +# 85| Type = [DoubleType] double +# 85| ValueCategory = prvalue(load) +# 86| 23: [ExprStmt] ExprStmt +# 86| 0: [AssignExpr] ... = ... +# 86| Type = [ArithmeticType] _Complex double +# 86| ValueCategory = prvalue +# 86| 0: [VariableAccess] cd +# 86| Type = [ArithmeticType] _Complex double +# 86| ValueCategory = lvalue +# 86| 1: [CStyleCast] (_Complex double)... +# 86| Conversion = [FloatingPointConversion] floating point conversion +# 86| Type = [ArithmeticType] _Complex double +# 86| ValueCategory = prvalue +# 86| expr: [VariableAccess] ld +# 86| Type = [LongDoubleType] long double +# 86| ValueCategory = prvalue(load) +# 87| 24: [ExprStmt] ExprStmt +# 87| 0: [AssignExpr] ... = ... +# 87| Type = [ArithmeticType] _Complex long double +# 87| ValueCategory = prvalue +# 87| 0: [VariableAccess] cld +# 87| Type = [ArithmeticType] _Complex long double +# 87| ValueCategory = lvalue +# 87| 1: [CStyleCast] (_Complex long double)... +# 87| Conversion = [FloatingPointConversion] floating point conversion +# 87| Type = [ArithmeticType] _Complex long double +# 87| ValueCategory = prvalue +# 87| expr: [VariableAccess] f +# 87| Type = [FloatType] float +# 87| ValueCategory = prvalue(load) +# 88| 25: [ExprStmt] ExprStmt +# 88| 0: [AssignExpr] ... = ... +# 88| Type = [ArithmeticType] _Complex long double +# 88| ValueCategory = prvalue +# 88| 0: [VariableAccess] cld +# 88| Type = [ArithmeticType] _Complex long double +# 88| ValueCategory = lvalue +# 88| 1: [CStyleCast] (_Complex long double)... +# 88| Conversion = [FloatingPointConversion] floating point conversion +# 88| Type = [ArithmeticType] _Complex long double +# 88| ValueCategory = prvalue +# 88| expr: [VariableAccess] d +# 88| Type = [DoubleType] double +# 88| ValueCategory = prvalue(load) +# 89| 26: [ExprStmt] ExprStmt +# 89| 0: [AssignExpr] ... = ... +# 89| Type = [ArithmeticType] _Complex long double +# 89| ValueCategory = prvalue +# 89| 0: [VariableAccess] cld +# 89| Type = [ArithmeticType] _Complex long double +# 89| ValueCategory = lvalue +# 89| 1: [CStyleCast] (_Complex long double)... +# 89| Conversion = [FloatingPointConversion] floating point conversion +# 89| Type = [ArithmeticType] _Complex long double +# 89| ValueCategory = prvalue +# 89| expr: [VariableAccess] ld +# 89| Type = [LongDoubleType] long double +# 89| ValueCategory = prvalue(load) +# 92| 27: [ExprStmt] ExprStmt +# 92| 0: [AssignExpr] ... = ... +# 92| Type = [FloatType] float +# 92| ValueCategory = prvalue +# 92| 0: [VariableAccess] f +# 92| Type = [FloatType] float +# 92| ValueCategory = lvalue +# 92| 1: [CStyleCast] (float)... +# 92| Conversion = [FloatingPointConversion] floating point conversion +# 92| Type = [FloatType] float +# 92| ValueCategory = prvalue +# 92| expr: [VariableAccess] cf +# 92| Type = [ArithmeticType] _Complex float +# 92| ValueCategory = prvalue(load) +# 93| 28: [ExprStmt] ExprStmt +# 93| 0: [AssignExpr] ... = ... +# 93| Type = [FloatType] float +# 93| ValueCategory = prvalue +# 93| 0: [VariableAccess] f +# 93| Type = [FloatType] float +# 93| ValueCategory = lvalue +# 93| 1: [CStyleCast] (float)... +# 93| Conversion = [FloatingPointConversion] floating point conversion +# 93| Type = [FloatType] float +# 93| ValueCategory = prvalue +# 93| expr: [VariableAccess] cd +# 93| Type = [ArithmeticType] _Complex double +# 93| ValueCategory = prvalue(load) +# 94| 29: [ExprStmt] ExprStmt +# 94| 0: [AssignExpr] ... = ... +# 94| Type = [FloatType] float +# 94| ValueCategory = prvalue +# 94| 0: [VariableAccess] f +# 94| Type = [FloatType] float +# 94| ValueCategory = lvalue +# 94| 1: [CStyleCast] (float)... +# 94| Conversion = [FloatingPointConversion] floating point conversion +# 94| Type = [FloatType] float +# 94| ValueCategory = prvalue +# 94| expr: [VariableAccess] cld +# 94| Type = [ArithmeticType] _Complex long double +# 94| ValueCategory = prvalue(load) +# 95| 30: [ExprStmt] ExprStmt +# 95| 0: [AssignExpr] ... = ... +# 95| Type = [DoubleType] double +# 95| ValueCategory = prvalue +# 95| 0: [VariableAccess] d +# 95| Type = [DoubleType] double +# 95| ValueCategory = lvalue +# 95| 1: [CStyleCast] (double)... +# 95| Conversion = [FloatingPointConversion] floating point conversion +# 95| Type = [DoubleType] double +# 95| ValueCategory = prvalue +# 95| expr: [VariableAccess] cf +# 95| Type = [ArithmeticType] _Complex float +# 95| ValueCategory = prvalue(load) +# 96| 31: [ExprStmt] ExprStmt +# 96| 0: [AssignExpr] ... = ... +# 96| Type = [DoubleType] double +# 96| ValueCategory = prvalue +# 96| 0: [VariableAccess] d +# 96| Type = [DoubleType] double +# 96| ValueCategory = lvalue +# 96| 1: [CStyleCast] (double)... +# 96| Conversion = [FloatingPointConversion] floating point conversion +# 96| Type = [DoubleType] double +# 96| ValueCategory = prvalue +# 96| expr: [VariableAccess] cd +# 96| Type = [ArithmeticType] _Complex double +# 96| ValueCategory = prvalue(load) +# 97| 32: [ExprStmt] ExprStmt +# 97| 0: [AssignExpr] ... = ... +# 97| Type = [DoubleType] double +# 97| ValueCategory = prvalue +# 97| 0: [VariableAccess] d +# 97| Type = [DoubleType] double +# 97| ValueCategory = lvalue +# 97| 1: [CStyleCast] (double)... +# 97| Conversion = [FloatingPointConversion] floating point conversion +# 97| Type = [DoubleType] double +# 97| ValueCategory = prvalue +# 97| expr: [VariableAccess] cld +# 97| Type = [ArithmeticType] _Complex long double +# 97| ValueCategory = prvalue(load) +# 98| 33: [ExprStmt] ExprStmt +# 98| 0: [AssignExpr] ... = ... +# 98| Type = [LongDoubleType] long double +# 98| ValueCategory = prvalue +# 98| 0: [VariableAccess] ld +# 98| Type = [LongDoubleType] long double +# 98| ValueCategory = lvalue +# 98| 1: [CStyleCast] (long double)... +# 98| Conversion = [FloatingPointConversion] floating point conversion +# 98| Type = [LongDoubleType] long double +# 98| ValueCategory = prvalue +# 98| expr: [VariableAccess] cf +# 98| Type = [ArithmeticType] _Complex float +# 98| ValueCategory = prvalue(load) +# 99| 34: [ExprStmt] ExprStmt +# 99| 0: [AssignExpr] ... = ... +# 99| Type = [LongDoubleType] long double +# 99| ValueCategory = prvalue +# 99| 0: [VariableAccess] ld +# 99| Type = [LongDoubleType] long double +# 99| ValueCategory = lvalue +# 99| 1: [CStyleCast] (long double)... +# 99| Conversion = [FloatingPointConversion] floating point conversion +# 99| Type = [LongDoubleType] long double +# 99| ValueCategory = prvalue +# 99| expr: [VariableAccess] cd +# 99| Type = [ArithmeticType] _Complex double +# 99| ValueCategory = prvalue(load) +# 100| 35: [ExprStmt] ExprStmt +# 100| 0: [AssignExpr] ... = ... +# 100| Type = [LongDoubleType] long double +# 100| ValueCategory = prvalue +# 100| 0: [VariableAccess] ld +# 100| Type = [LongDoubleType] long double +# 100| ValueCategory = lvalue +# 100| 1: [CStyleCast] (long double)... +# 100| Conversion = [FloatingPointConversion] floating point conversion +# 100| Type = [LongDoubleType] long double +# 100| ValueCategory = prvalue +# 100| expr: [VariableAccess] cld +# 100| Type = [ArithmeticType] _Complex long double +# 100| ValueCategory = prvalue(load) +# 103| 36: [ExprStmt] ExprStmt +# 103| 0: [AssignExpr] ... = ... +# 103| Type = [ArithmeticType] _Complex float +# 103| ValueCategory = prvalue +# 103| 0: [VariableAccess] cf +# 103| Type = [ArithmeticType] _Complex float +# 103| ValueCategory = lvalue +# 103| 1: [CStyleCast] (_Complex float)... +# 103| Conversion = [FloatingPointConversion] floating point conversion +# 103| Type = [ArithmeticType] _Complex float +# 103| ValueCategory = prvalue +# 103| expr: [VariableAccess] jf +# 103| Type = [ArithmeticType] _Imaginary float +# 103| ValueCategory = prvalue(load) +# 104| 37: [ExprStmt] ExprStmt +# 104| 0: [AssignExpr] ... = ... +# 104| Type = [ArithmeticType] _Complex float +# 104| ValueCategory = prvalue +# 104| 0: [VariableAccess] cf +# 104| Type = [ArithmeticType] _Complex float +# 104| ValueCategory = lvalue +# 104| 1: [CStyleCast] (_Complex float)... +# 104| Conversion = [FloatingPointConversion] floating point conversion +# 104| Type = [ArithmeticType] _Complex float +# 104| ValueCategory = prvalue +# 104| expr: [VariableAccess] jd +# 104| Type = [ArithmeticType] _Imaginary double +# 104| ValueCategory = prvalue(load) +# 105| 38: [ExprStmt] ExprStmt +# 105| 0: [AssignExpr] ... = ... +# 105| Type = [ArithmeticType] _Complex float +# 105| ValueCategory = prvalue +# 105| 0: [VariableAccess] cf +# 105| Type = [ArithmeticType] _Complex float +# 105| ValueCategory = lvalue +# 105| 1: [CStyleCast] (_Complex float)... +# 105| Conversion = [FloatingPointConversion] floating point conversion +# 105| Type = [ArithmeticType] _Complex float +# 105| ValueCategory = prvalue +# 105| expr: [VariableAccess] jld +# 105| Type = [ArithmeticType] _Imaginary long double +# 105| ValueCategory = prvalue(load) +# 106| 39: [ExprStmt] ExprStmt +# 106| 0: [AssignExpr] ... = ... +# 106| Type = [ArithmeticType] _Complex double +# 106| ValueCategory = prvalue +# 106| 0: [VariableAccess] cd +# 106| Type = [ArithmeticType] _Complex double +# 106| ValueCategory = lvalue +# 106| 1: [CStyleCast] (_Complex double)... +# 106| Conversion = [FloatingPointConversion] floating point conversion +# 106| Type = [ArithmeticType] _Complex double +# 106| ValueCategory = prvalue +# 106| expr: [VariableAccess] jf +# 106| Type = [ArithmeticType] _Imaginary float +# 106| ValueCategory = prvalue(load) +# 107| 40: [ExprStmt] ExprStmt +# 107| 0: [AssignExpr] ... = ... +# 107| Type = [ArithmeticType] _Complex double +# 107| ValueCategory = prvalue +# 107| 0: [VariableAccess] cd +# 107| Type = [ArithmeticType] _Complex double +# 107| ValueCategory = lvalue +# 107| 1: [CStyleCast] (_Complex double)... +# 107| Conversion = [FloatingPointConversion] floating point conversion +# 107| Type = [ArithmeticType] _Complex double +# 107| ValueCategory = prvalue +# 107| expr: [VariableAccess] jd +# 107| Type = [ArithmeticType] _Imaginary double +# 107| ValueCategory = prvalue(load) +# 108| 41: [ExprStmt] ExprStmt +# 108| 0: [AssignExpr] ... = ... +# 108| Type = [ArithmeticType] _Complex double +# 108| ValueCategory = prvalue +# 108| 0: [VariableAccess] cd +# 108| Type = [ArithmeticType] _Complex double +# 108| ValueCategory = lvalue +# 108| 1: [CStyleCast] (_Complex double)... +# 108| Conversion = [FloatingPointConversion] floating point conversion +# 108| Type = [ArithmeticType] _Complex double +# 108| ValueCategory = prvalue +# 108| expr: [VariableAccess] jld +# 108| Type = [ArithmeticType] _Imaginary long double +# 108| ValueCategory = prvalue(load) +# 109| 42: [ExprStmt] ExprStmt +# 109| 0: [AssignExpr] ... = ... +# 109| Type = [ArithmeticType] _Complex long double +# 109| ValueCategory = prvalue +# 109| 0: [VariableAccess] cld +# 109| Type = [ArithmeticType] _Complex long double +# 109| ValueCategory = lvalue +# 109| 1: [CStyleCast] (_Complex long double)... +# 109| Conversion = [FloatingPointConversion] floating point conversion +# 109| Type = [ArithmeticType] _Complex long double +# 109| ValueCategory = prvalue +# 109| expr: [VariableAccess] jf +# 109| Type = [ArithmeticType] _Imaginary float +# 109| ValueCategory = prvalue(load) +# 110| 43: [ExprStmt] ExprStmt +# 110| 0: [AssignExpr] ... = ... +# 110| Type = [ArithmeticType] _Complex long double +# 110| ValueCategory = prvalue +# 110| 0: [VariableAccess] cld +# 110| Type = [ArithmeticType] _Complex long double +# 110| ValueCategory = lvalue +# 110| 1: [CStyleCast] (_Complex long double)... +# 110| Conversion = [FloatingPointConversion] floating point conversion +# 110| Type = [ArithmeticType] _Complex long double +# 110| ValueCategory = prvalue +# 110| expr: [VariableAccess] jd +# 110| Type = [ArithmeticType] _Imaginary double +# 110| ValueCategory = prvalue(load) +# 111| 44: [ExprStmt] ExprStmt +# 111| 0: [AssignExpr] ... = ... +# 111| Type = [ArithmeticType] _Complex long double +# 111| ValueCategory = prvalue +# 111| 0: [VariableAccess] cld +# 111| Type = [ArithmeticType] _Complex long double +# 111| ValueCategory = lvalue +# 111| 1: [CStyleCast] (_Complex long double)... +# 111| Conversion = [FloatingPointConversion] floating point conversion +# 111| Type = [ArithmeticType] _Complex long double +# 111| ValueCategory = prvalue +# 111| expr: [VariableAccess] jld +# 111| Type = [ArithmeticType] _Imaginary long double +# 111| ValueCategory = prvalue(load) +# 114| 45: [ExprStmt] ExprStmt +# 114| 0: [AssignExpr] ... = ... +# 114| Type = [ArithmeticType] _Imaginary float +# 114| ValueCategory = prvalue +# 114| 0: [VariableAccess] jf +# 114| Type = [ArithmeticType] _Imaginary float +# 114| ValueCategory = lvalue +# 114| 1: [CStyleCast] (_Imaginary float)... +# 114| Conversion = [FloatingPointConversion] floating point conversion +# 114| Type = [ArithmeticType] _Imaginary float +# 114| ValueCategory = prvalue +# 114| expr: [VariableAccess] cf +# 114| Type = [ArithmeticType] _Complex float +# 114| ValueCategory = prvalue(load) +# 115| 46: [ExprStmt] ExprStmt +# 115| 0: [AssignExpr] ... = ... +# 115| Type = [ArithmeticType] _Imaginary float +# 115| ValueCategory = prvalue +# 115| 0: [VariableAccess] jf +# 115| Type = [ArithmeticType] _Imaginary float +# 115| ValueCategory = lvalue +# 115| 1: [CStyleCast] (_Imaginary float)... +# 115| Conversion = [FloatingPointConversion] floating point conversion +# 115| Type = [ArithmeticType] _Imaginary float +# 115| ValueCategory = prvalue +# 115| expr: [VariableAccess] cd +# 115| Type = [ArithmeticType] _Complex double +# 115| ValueCategory = prvalue(load) +# 116| 47: [ExprStmt] ExprStmt +# 116| 0: [AssignExpr] ... = ... +# 116| Type = [ArithmeticType] _Imaginary float +# 116| ValueCategory = prvalue +# 116| 0: [VariableAccess] jf +# 116| Type = [ArithmeticType] _Imaginary float +# 116| ValueCategory = lvalue +# 116| 1: [CStyleCast] (_Imaginary float)... +# 116| Conversion = [FloatingPointConversion] floating point conversion +# 116| Type = [ArithmeticType] _Imaginary float +# 116| ValueCategory = prvalue +# 116| expr: [VariableAccess] cld +# 116| Type = [ArithmeticType] _Complex long double +# 116| ValueCategory = prvalue(load) +# 117| 48: [ExprStmt] ExprStmt +# 117| 0: [AssignExpr] ... = ... +# 117| Type = [ArithmeticType] _Imaginary double +# 117| ValueCategory = prvalue +# 117| 0: [VariableAccess] jd +# 117| Type = [ArithmeticType] _Imaginary double +# 117| ValueCategory = lvalue +# 117| 1: [CStyleCast] (_Imaginary double)... +# 117| Conversion = [FloatingPointConversion] floating point conversion +# 117| Type = [ArithmeticType] _Imaginary double +# 117| ValueCategory = prvalue +# 117| expr: [VariableAccess] cf +# 117| Type = [ArithmeticType] _Complex float +# 117| ValueCategory = prvalue(load) +# 118| 49: [ExprStmt] ExprStmt +# 118| 0: [AssignExpr] ... = ... +# 118| Type = [ArithmeticType] _Imaginary double +# 118| ValueCategory = prvalue +# 118| 0: [VariableAccess] jd +# 118| Type = [ArithmeticType] _Imaginary double +# 118| ValueCategory = lvalue +# 118| 1: [CStyleCast] (_Imaginary double)... +# 118| Conversion = [FloatingPointConversion] floating point conversion +# 118| Type = [ArithmeticType] _Imaginary double +# 118| ValueCategory = prvalue +# 118| expr: [VariableAccess] cd +# 118| Type = [ArithmeticType] _Complex double +# 118| ValueCategory = prvalue(load) +# 119| 50: [ExprStmt] ExprStmt +# 119| 0: [AssignExpr] ... = ... +# 119| Type = [ArithmeticType] _Imaginary double +# 119| ValueCategory = prvalue +# 119| 0: [VariableAccess] jd +# 119| Type = [ArithmeticType] _Imaginary double +# 119| ValueCategory = lvalue +# 119| 1: [CStyleCast] (_Imaginary double)... +# 119| Conversion = [FloatingPointConversion] floating point conversion +# 119| Type = [ArithmeticType] _Imaginary double +# 119| ValueCategory = prvalue +# 119| expr: [VariableAccess] cld +# 119| Type = [ArithmeticType] _Complex long double +# 119| ValueCategory = prvalue(load) +# 120| 51: [ExprStmt] ExprStmt +# 120| 0: [AssignExpr] ... = ... +# 120| Type = [ArithmeticType] _Imaginary long double +# 120| ValueCategory = prvalue +# 120| 0: [VariableAccess] jld +# 120| Type = [ArithmeticType] _Imaginary long double +# 120| ValueCategory = lvalue +# 120| 1: [CStyleCast] (_Imaginary long double)... +# 120| Conversion = [FloatingPointConversion] floating point conversion +# 120| Type = [ArithmeticType] _Imaginary long double +# 120| ValueCategory = prvalue +# 120| expr: [VariableAccess] cf +# 120| Type = [ArithmeticType] _Complex float +# 120| ValueCategory = prvalue(load) +# 121| 52: [ExprStmt] ExprStmt +# 121| 0: [AssignExpr] ... = ... +# 121| Type = [ArithmeticType] _Imaginary long double +# 121| ValueCategory = prvalue +# 121| 0: [VariableAccess] jld +# 121| Type = [ArithmeticType] _Imaginary long double +# 121| ValueCategory = lvalue +# 121| 1: [CStyleCast] (_Imaginary long double)... +# 121| Conversion = [FloatingPointConversion] floating point conversion +# 121| Type = [ArithmeticType] _Imaginary long double +# 121| ValueCategory = prvalue +# 121| expr: [VariableAccess] cd +# 121| Type = [ArithmeticType] _Complex double +# 121| ValueCategory = prvalue(load) +# 122| 53: [ExprStmt] ExprStmt +# 122| 0: [AssignExpr] ... = ... +# 122| Type = [ArithmeticType] _Imaginary long double +# 122| ValueCategory = prvalue +# 122| 0: [VariableAccess] jld +# 122| Type = [ArithmeticType] _Imaginary long double +# 122| ValueCategory = lvalue +# 122| 1: [CStyleCast] (_Imaginary long double)... +# 122| Conversion = [FloatingPointConversion] floating point conversion +# 122| Type = [ArithmeticType] _Imaginary long double +# 122| ValueCategory = prvalue +# 122| expr: [VariableAccess] cld +# 122| Type = [ArithmeticType] _Complex long double +# 122| ValueCategory = prvalue(load) +# 125| 54: [ExprStmt] ExprStmt +# 125| 0: [AssignExpr] ... = ... +# 125| Type = [ArithmeticType] _Imaginary float +# 125| ValueCategory = prvalue +# 125| 0: [VariableAccess] jf +# 125| Type = [ArithmeticType] _Imaginary float +# 125| ValueCategory = lvalue +# 125| 1: [CStyleCast] (_Imaginary float)... +# 125| Conversion = [FloatingPointConversion] floating point conversion +# 125| Type = [ArithmeticType] _Imaginary float +# 125| ValueCategory = prvalue +# 125| expr: [VariableAccess] f +# 125| Type = [FloatType] float +# 125| ValueCategory = prvalue(load) +# 126| 55: [ExprStmt] ExprStmt +# 126| 0: [AssignExpr] ... = ... +# 126| Type = [ArithmeticType] _Imaginary float +# 126| ValueCategory = prvalue +# 126| 0: [VariableAccess] jf +# 126| Type = [ArithmeticType] _Imaginary float +# 126| ValueCategory = lvalue +# 126| 1: [CStyleCast] (_Imaginary float)... +# 126| Conversion = [FloatingPointConversion] floating point conversion +# 126| Type = [ArithmeticType] _Imaginary float +# 126| ValueCategory = prvalue +# 126| expr: [VariableAccess] d +# 126| Type = [DoubleType] double +# 126| ValueCategory = prvalue(load) +# 127| 56: [ExprStmt] ExprStmt +# 127| 0: [AssignExpr] ... = ... +# 127| Type = [ArithmeticType] _Imaginary float +# 127| ValueCategory = prvalue +# 127| 0: [VariableAccess] jf +# 127| Type = [ArithmeticType] _Imaginary float +# 127| ValueCategory = lvalue +# 127| 1: [CStyleCast] (_Imaginary float)... +# 127| Conversion = [FloatingPointConversion] floating point conversion +# 127| Type = [ArithmeticType] _Imaginary float +# 127| ValueCategory = prvalue +# 127| expr: [VariableAccess] ld +# 127| Type = [LongDoubleType] long double +# 127| ValueCategory = prvalue(load) +# 128| 57: [ExprStmt] ExprStmt +# 128| 0: [AssignExpr] ... = ... +# 128| Type = [ArithmeticType] _Imaginary double +# 128| ValueCategory = prvalue +# 128| 0: [VariableAccess] jd +# 128| Type = [ArithmeticType] _Imaginary double +# 128| ValueCategory = lvalue +# 128| 1: [CStyleCast] (_Imaginary double)... +# 128| Conversion = [FloatingPointConversion] floating point conversion +# 128| Type = [ArithmeticType] _Imaginary double +# 128| ValueCategory = prvalue +# 128| expr: [VariableAccess] f +# 128| Type = [FloatType] float +# 128| ValueCategory = prvalue(load) +# 129| 58: [ExprStmt] ExprStmt +# 129| 0: [AssignExpr] ... = ... +# 129| Type = [ArithmeticType] _Imaginary double +# 129| ValueCategory = prvalue +# 129| 0: [VariableAccess] jd +# 129| Type = [ArithmeticType] _Imaginary double +# 129| ValueCategory = lvalue +# 129| 1: [CStyleCast] (_Imaginary double)... +# 129| Conversion = [FloatingPointConversion] floating point conversion +# 129| Type = [ArithmeticType] _Imaginary double +# 129| ValueCategory = prvalue +# 129| expr: [VariableAccess] d +# 129| Type = [DoubleType] double +# 129| ValueCategory = prvalue(load) +# 130| 59: [ExprStmt] ExprStmt +# 130| 0: [AssignExpr] ... = ... +# 130| Type = [ArithmeticType] _Imaginary double +# 130| ValueCategory = prvalue +# 130| 0: [VariableAccess] jd +# 130| Type = [ArithmeticType] _Imaginary double +# 130| ValueCategory = lvalue +# 130| 1: [CStyleCast] (_Imaginary double)... +# 130| Conversion = [FloatingPointConversion] floating point conversion +# 130| Type = [ArithmeticType] _Imaginary double +# 130| ValueCategory = prvalue +# 130| expr: [VariableAccess] ld +# 130| Type = [LongDoubleType] long double +# 130| ValueCategory = prvalue(load) +# 131| 60: [ExprStmt] ExprStmt +# 131| 0: [AssignExpr] ... = ... +# 131| Type = [ArithmeticType] _Imaginary long double +# 131| ValueCategory = prvalue +# 131| 0: [VariableAccess] jld +# 131| Type = [ArithmeticType] _Imaginary long double +# 131| ValueCategory = lvalue +# 131| 1: [CStyleCast] (_Imaginary long double)... +# 131| Conversion = [FloatingPointConversion] floating point conversion +# 131| Type = [ArithmeticType] _Imaginary long double +# 131| ValueCategory = prvalue +# 131| expr: [VariableAccess] f +# 131| Type = [FloatType] float +# 131| ValueCategory = prvalue(load) +# 132| 61: [ExprStmt] ExprStmt +# 132| 0: [AssignExpr] ... = ... +# 132| Type = [ArithmeticType] _Imaginary long double +# 132| ValueCategory = prvalue +# 132| 0: [VariableAccess] jld +# 132| Type = [ArithmeticType] _Imaginary long double +# 132| ValueCategory = lvalue +# 132| 1: [CStyleCast] (_Imaginary long double)... +# 132| Conversion = [FloatingPointConversion] floating point conversion +# 132| Type = [ArithmeticType] _Imaginary long double +# 132| ValueCategory = prvalue +# 132| expr: [VariableAccess] d +# 132| Type = [DoubleType] double +# 132| ValueCategory = prvalue(load) +# 133| 62: [ExprStmt] ExprStmt +# 133| 0: [AssignExpr] ... = ... +# 133| Type = [ArithmeticType] _Imaginary long double +# 133| ValueCategory = prvalue +# 133| 0: [VariableAccess] jld +# 133| Type = [ArithmeticType] _Imaginary long double +# 133| ValueCategory = lvalue +# 133| 1: [CStyleCast] (_Imaginary long double)... +# 133| Conversion = [FloatingPointConversion] floating point conversion +# 133| Type = [ArithmeticType] _Imaginary long double +# 133| ValueCategory = prvalue +# 133| expr: [VariableAccess] ld +# 133| Type = [LongDoubleType] long double +# 133| ValueCategory = prvalue(load) +# 136| 63: [ExprStmt] ExprStmt +# 136| 0: [AssignExpr] ... = ... +# 136| Type = [FloatType] float +# 136| ValueCategory = prvalue +# 136| 0: [VariableAccess] f +# 136| Type = [FloatType] float +# 136| ValueCategory = lvalue +# 136| 1: [CStyleCast] (float)... +# 136| Conversion = [FloatingPointConversion] floating point conversion +# 136| Type = [FloatType] float +# 136| ValueCategory = prvalue +# 136| expr: [VariableAccess] jf +# 136| Type = [ArithmeticType] _Imaginary float +# 136| ValueCategory = prvalue(load) +# 137| 64: [ExprStmt] ExprStmt +# 137| 0: [AssignExpr] ... = ... +# 137| Type = [FloatType] float +# 137| ValueCategory = prvalue +# 137| 0: [VariableAccess] f +# 137| Type = [FloatType] float +# 137| ValueCategory = lvalue +# 137| 1: [CStyleCast] (float)... +# 137| Conversion = [FloatingPointConversion] floating point conversion +# 137| Type = [FloatType] float +# 137| ValueCategory = prvalue +# 137| expr: [VariableAccess] jd +# 137| Type = [ArithmeticType] _Imaginary double +# 137| ValueCategory = prvalue(load) +# 138| 65: [ExprStmt] ExprStmt +# 138| 0: [AssignExpr] ... = ... +# 138| Type = [FloatType] float +# 138| ValueCategory = prvalue +# 138| 0: [VariableAccess] f +# 138| Type = [FloatType] float +# 138| ValueCategory = lvalue +# 138| 1: [CStyleCast] (float)... +# 138| Conversion = [FloatingPointConversion] floating point conversion +# 138| Type = [FloatType] float +# 138| ValueCategory = prvalue +# 138| expr: [VariableAccess] jld +# 138| Type = [ArithmeticType] _Imaginary long double +# 138| ValueCategory = prvalue(load) +# 139| 66: [ExprStmt] ExprStmt +# 139| 0: [AssignExpr] ... = ... +# 139| Type = [DoubleType] double +# 139| ValueCategory = prvalue +# 139| 0: [VariableAccess] d +# 139| Type = [DoubleType] double +# 139| ValueCategory = lvalue +# 139| 1: [CStyleCast] (double)... +# 139| Conversion = [FloatingPointConversion] floating point conversion +# 139| Type = [DoubleType] double +# 139| ValueCategory = prvalue +# 139| expr: [VariableAccess] jf +# 139| Type = [ArithmeticType] _Imaginary float +# 139| ValueCategory = prvalue(load) +# 140| 67: [ExprStmt] ExprStmt +# 140| 0: [AssignExpr] ... = ... +# 140| Type = [DoubleType] double +# 140| ValueCategory = prvalue +# 140| 0: [VariableAccess] d +# 140| Type = [DoubleType] double +# 140| ValueCategory = lvalue +# 140| 1: [CStyleCast] (double)... +# 140| Conversion = [FloatingPointConversion] floating point conversion +# 140| Type = [DoubleType] double +# 140| ValueCategory = prvalue +# 140| expr: [VariableAccess] jd +# 140| Type = [ArithmeticType] _Imaginary double +# 140| ValueCategory = prvalue(load) +# 141| 68: [ExprStmt] ExprStmt +# 141| 0: [AssignExpr] ... = ... +# 141| Type = [DoubleType] double +# 141| ValueCategory = prvalue +# 141| 0: [VariableAccess] d +# 141| Type = [DoubleType] double +# 141| ValueCategory = lvalue +# 141| 1: [CStyleCast] (double)... +# 141| Conversion = [FloatingPointConversion] floating point conversion +# 141| Type = [DoubleType] double +# 141| ValueCategory = prvalue +# 141| expr: [VariableAccess] jld +# 141| Type = [ArithmeticType] _Imaginary long double +# 141| ValueCategory = prvalue(load) +# 142| 69: [ExprStmt] ExprStmt +# 142| 0: [AssignExpr] ... = ... +# 142| Type = [LongDoubleType] long double +# 142| ValueCategory = prvalue +# 142| 0: [VariableAccess] ld +# 142| Type = [LongDoubleType] long double +# 142| ValueCategory = lvalue +# 142| 1: [CStyleCast] (long double)... +# 142| Conversion = [FloatingPointConversion] floating point conversion +# 142| Type = [LongDoubleType] long double +# 142| ValueCategory = prvalue +# 142| expr: [VariableAccess] jf +# 142| Type = [ArithmeticType] _Imaginary float +# 142| ValueCategory = prvalue(load) +# 143| 70: [ExprStmt] ExprStmt +# 143| 0: [AssignExpr] ... = ... +# 143| Type = [LongDoubleType] long double +# 143| ValueCategory = prvalue +# 143| 0: [VariableAccess] ld +# 143| Type = [LongDoubleType] long double +# 143| ValueCategory = lvalue +# 143| 1: [CStyleCast] (long double)... +# 143| Conversion = [FloatingPointConversion] floating point conversion +# 143| Type = [LongDoubleType] long double +# 143| ValueCategory = prvalue +# 143| expr: [VariableAccess] jd +# 143| Type = [ArithmeticType] _Imaginary double +# 143| ValueCategory = prvalue(load) +# 144| 71: [ExprStmt] ExprStmt +# 144| 0: [AssignExpr] ... = ... +# 144| Type = [LongDoubleType] long double +# 144| ValueCategory = prvalue +# 144| 0: [VariableAccess] ld +# 144| Type = [LongDoubleType] long double +# 144| ValueCategory = lvalue +# 144| 1: [CStyleCast] (long double)... +# 144| Conversion = [FloatingPointConversion] floating point conversion +# 144| Type = [LongDoubleType] long double +# 144| ValueCategory = prvalue +# 144| expr: [VariableAccess] jld +# 144| Type = [ArithmeticType] _Imaginary long double +# 144| ValueCategory = prvalue(load) +# 145| 72: [ReturnStmt] return ... ir.cpp: # 1| [TopLevelFunction] void Constants() # 1| params: diff --git a/cpp/ql/test/library-tests/ir/ir/complex.c b/cpp/ql/test/library-tests/ir/ir/complex.c index 51775832586..d2009778ae5 100644 --- a/cpp/ql/test/library-tests/ir/ir/complex.c +++ b/cpp/ql/test/library-tests/ir/ir/complex.c @@ -1,5 +1,147 @@ -void complex_math(void) { - _Complex float cf = 2.0 + 1.0if; - _Complex float cf2 = cf * cf; - double d = cf2; +void complex_literals(void) { + _Complex float cf = 2.0; + cf = __I__; + _Complex double cd = 3.0; + cd = __I__; + _Complex long double cld = 5.0; + cld = __I__; + + _Imaginary float jf = __I__; + _Imaginary double jd = __I__; + _Imaginary long double jld = __I__; } + +void complex_arithmetic(void) { + float f1 = 5.0; + float f2 = 7.0; + float f3; + _Complex float cf1 = 2.0; + _Complex float cf2 = __I__; + _Complex float cf3; + _Imaginary float jf1 = __I__; + _Imaginary float jf2 = __I__; + _Imaginary float jf3; + + // unaryop _Complex + cf3 = +cf1; + cf3 = -cf1; + + // _Complex binaryop _Complex + cf3 = cf1 + cf2; + cf3 = cf1 - cf2; + cf3 = cf1 * cf2; + cf3 = cf1 / cf2; + + // unaryop _Imaginary + jf3 = +jf1; + jf3 = -jf1; + + // _Imaginary binaryop _Imaginary + jf3 = jf1 + jf2; + jf3 = jf1 - jf2; + f3 = jf1 * jf2; // Result is _Real + f3 = jf1 / jf2; // Result is _Real + + // _Imaginary binaryop _Real + cf3 = jf1 + f2; + cf3 = jf1 - f2; + jf3 = jf1 * f2; // Result is _Imaginary + jf3 = jf1 / f2; // Result is _Imaginary + + // _Real binaryop _Imaginary + cf3 = f1 + jf2; + cf3 = f1 - jf2; + jf3 = f1 * jf2; // Result is _Imaginary + jf3 = f1 / jf2; // Result is _Imaginary +} + +void complex_conversions(void) { + float f = 2.0; + double d = 3.0; + long double ld = 5.0; + _Complex float cf = 7.0; + _Complex double cd = 11.0; + _Complex long double cld = 13.0; + _Imaginary float jf = __I__; + _Imaginary double jd = __I__; + _Imaginary long double jld = __I__; + + // _Complex to _Complex + cf = cf; + cf = cd; + cf = cld; + cd = cf; + cd = cd; + cd = cld; + cld = cf; + cld = cd; + cld = cld; + + // _Real to _Complex + cf = f; + cf = d; + cf = ld; + cd = f; + cd = d; + cd = ld; + cld = f; + cld = d; + cld = ld; + + // _Complex to _Real + f = cf; + f = cd; + f = cld; + d = cf; + d = cd; + d = cld; + ld = cf; + ld = cd; + ld = cld; + + // _Imaginary to _Complex + cf = jf; + cf = jd; + cf = jld; + cd = jf; + cd = jd; + cd = jld; + cld = jf; + cld = jd; + cld = jld; + + // _Complex to _Imaginary + jf = cf; + jf = cd; + jf = cld; + jd = cf; + jd = cd; + jd = cld; + jld = cf; + jld = cd; + jld = cld; + + // _Real to _Imaginary + jf = f; + jf = d; + jf = ld; + jd = f; + jd = d; + jd = ld; + jld = f; + jld = d; + jld = ld; + + // _Imaginary to _Real + f = jf; + f = jd; + f = jld; + d = jf; + d = jd; + d = jld; + ld = jf; + ld = jd; + ld = jld; +} + +// semmle-extractor-options: --microsoft --edg --c99 diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 66c6711e645..b5f57acaa4c 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -125,37 +125,578 @@ clang.cpp: # 5| v5_9(void) = ExitFunction : complex.c: -# 1| void complex_math() +# 1| void complex_literals() # 1| Block 0 -# 1| v1_1(void) = EnterFunction : -# 1| mu1_2(unknown) = AliasedDefinition : -# 1| mu1_3(unknown) = InitializeNonLocal : -# 1| mu1_4(unknown) = UnmodeledDefinition : -# 2| r2_1(glval<_Complex float>) = VariableAddress[cf] : -# 2| r2_2(double) = Constant[2.0] : -# 2| r2_3(_Complex double) = Convert : r2_2 -# 2| r2_4(_Complex float) = Constant[(0.0,1.0i)] : -# 2| r2_5(_Complex double) = Convert : r2_4 -# 2| r2_6(_Complex double) = Add : r2_3, r2_5 -# 2| r2_7(_Complex float) = Convert : r2_6 -# 2| mu2_8(_Complex float) = Store : &:r2_1, r2_7 -# 3| r3_1(glval<_Complex float>) = VariableAddress[cf2] : -# 3| r3_2(glval<_Complex float>) = VariableAddress[cf] : -# 3| r3_3(_Complex float) = Load : &:r3_2, ~mu1_4 -# 3| r3_4(glval<_Complex float>) = VariableAddress[cf] : -# 3| r3_5(_Complex float) = Load : &:r3_4, ~mu1_4 -# 3| r3_6(_Complex float) = Mul : r3_3, r3_5 -# 3| mu3_7(_Complex float) = Store : &:r3_1, r3_6 -# 4| r4_1(glval) = VariableAddress[d] : -# 4| r4_2(glval<_Complex float>) = VariableAddress[cf2] : -# 4| r4_3(_Complex float) = Load : &:r4_2, ~mu1_4 -# 4| r4_4(double) = Convert : r4_3 -# 4| mu4_5(double) = Store : &:r4_1, r4_4 -# 5| v5_1(void) = NoOp : -# 1| v1_5(void) = ReturnVoid : -# 1| v1_6(void) = UnmodeledUse : mu* -# 1| v1_7(void) = AliasedUse : ~mu1_4 -# 1| v1_8(void) = ExitFunction : +# 1| v1_1(void) = EnterFunction : +# 1| mu1_2(unknown) = AliasedDefinition : +# 1| mu1_3(unknown) = InitializeNonLocal : +# 1| mu1_4(unknown) = UnmodeledDefinition : +# 2| r2_1(glval<_Complex float>) = VariableAddress[cf] : +# 2| r2_2(double) = Constant[2.0] : +# 2| r2_3(_Complex float) = Convert : r2_2 +# 2| mu2_4(_Complex float) = Store : &:r2_1, r2_3 +# 3| r3_1(_Imaginary float) = Constant[1.0i] : +# 3| r3_2(_Complex float) = Convert : r3_1 +# 3| r3_3(glval<_Complex float>) = VariableAddress[cf] : +# 3| mu3_4(_Complex float) = Store : &:r3_3, r3_2 +# 4| r4_1(glval<_Complex double>) = VariableAddress[cd] : +# 4| r4_2(double) = Constant[3.0] : +# 4| r4_3(_Complex double) = Convert : r4_2 +# 4| mu4_4(_Complex double) = Store : &:r4_1, r4_3 +# 5| r5_1(_Imaginary float) = Constant[1.0i] : +# 5| r5_2(_Complex double) = Convert : r5_1 +# 5| r5_3(glval<_Complex double>) = VariableAddress[cd] : +# 5| mu5_4(_Complex double) = Store : &:r5_3, r5_2 +# 6| r6_1(glval<_Complex long double>) = VariableAddress[cld] : +# 6| r6_2(double) = Constant[5.0] : +# 6| r6_3(_Complex long double) = Convert : r6_2 +# 6| mu6_4(_Complex long double) = Store : &:r6_1, r6_3 +# 7| r7_1(_Imaginary float) = Constant[1.0i] : +# 7| r7_2(_Complex long double) = Convert : r7_1 +# 7| r7_3(glval<_Complex long double>) = VariableAddress[cld] : +# 7| mu7_4(_Complex long double) = Store : &:r7_3, r7_2 +# 9| r9_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 9| r9_2(_Imaginary float) = Constant[1.0i] : +# 9| mu9_3(_Imaginary float) = Store : &:r9_1, r9_2 +# 10| r10_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 10| r10_2(_Imaginary float) = Constant[1.0i] : +# 10| r10_3(_Imaginary double) = Convert : r10_2 +# 10| mu10_4(_Imaginary double) = Store : &:r10_1, r10_3 +# 11| r11_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 11| r11_2(_Imaginary float) = Constant[1.0i] : +# 11| r11_3(_Imaginary long double) = Convert : r11_2 +# 11| mu11_4(_Imaginary long double) = Store : &:r11_1, r11_3 +# 12| v12_1(void) = NoOp : +# 1| v1_5(void) = ReturnVoid : +# 1| v1_6(void) = UnmodeledUse : mu* +# 1| v1_7(void) = AliasedUse : ~mu1_4 +# 1| v1_8(void) = ExitFunction : + +# 14| void complex_arithmetic() +# 14| Block 0 +# 14| v14_1(void) = EnterFunction : +# 14| mu14_2(unknown) = AliasedDefinition : +# 14| mu14_3(unknown) = InitializeNonLocal : +# 14| mu14_4(unknown) = UnmodeledDefinition : +# 15| r15_1(glval) = VariableAddress[f1] : +# 15| r15_2(float) = Constant[5.0] : +# 15| mu15_3(float) = Store : &:r15_1, r15_2 +# 16| r16_1(glval) = VariableAddress[f2] : +# 16| r16_2(float) = Constant[7.0] : +# 16| mu16_3(float) = Store : &:r16_1, r16_2 +# 17| r17_1(glval) = VariableAddress[f3] : +# 17| mu17_2(float) = Uninitialized[f3] : &:r17_1 +# 18| r18_1(glval<_Complex float>) = VariableAddress[cf1] : +# 18| r18_2(double) = Constant[2.0] : +# 18| r18_3(_Complex float) = Convert : r18_2 +# 18| mu18_4(_Complex float) = Store : &:r18_1, r18_3 +# 19| r19_1(glval<_Complex float>) = VariableAddress[cf2] : +# 19| r19_2(_Imaginary float) = Constant[1.0i] : +# 19| r19_3(_Complex float) = Convert : r19_2 +# 19| mu19_4(_Complex float) = Store : &:r19_1, r19_3 +# 20| r20_1(glval<_Complex float>) = VariableAddress[cf3] : +# 20| mu20_2(_Complex float) = Uninitialized[cf3] : &:r20_1 +# 21| r21_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 21| r21_2(_Imaginary float) = Constant[1.0i] : +# 21| mu21_3(_Imaginary float) = Store : &:r21_1, r21_2 +# 22| r22_1(glval<_Imaginary float>) = VariableAddress[jf2] : +# 22| r22_2(_Imaginary float) = Constant[1.0i] : +# 22| mu22_3(_Imaginary float) = Store : &:r22_1, r22_2 +# 23| r23_1(glval<_Imaginary float>) = VariableAddress[jf3] : +# 23| mu23_2(_Imaginary float) = Uninitialized[jf3] : &:r23_1 +# 26| r26_1(glval<_Complex float>) = VariableAddress[cf1] : +# 26| r26_2(_Complex float) = Load : &:r26_1, ~mu14_4 +# 26| r26_3(_Complex float) = CopyValue : r26_2 +# 26| r26_4(glval<_Complex float>) = VariableAddress[cf3] : +# 26| mu26_5(_Complex float) = Store : &:r26_4, r26_3 +# 27| r27_1(glval<_Complex float>) = VariableAddress[cf1] : +# 27| r27_2(_Complex float) = Load : &:r27_1, ~mu14_4 +# 27| r27_3(_Complex float) = Negate : r27_2 +# 27| r27_4(glval<_Complex float>) = VariableAddress[cf3] : +# 27| mu27_5(_Complex float) = Store : &:r27_4, r27_3 +# 30| r30_1(glval<_Complex float>) = VariableAddress[cf1] : +# 30| r30_2(_Complex float) = Load : &:r30_1, ~mu14_4 +# 30| r30_3(glval<_Complex float>) = VariableAddress[cf2] : +# 30| r30_4(_Complex float) = Load : &:r30_3, ~mu14_4 +# 30| r30_5(_Complex float) = Add : r30_2, r30_4 +# 30| r30_6(glval<_Complex float>) = VariableAddress[cf3] : +# 30| mu30_7(_Complex float) = Store : &:r30_6, r30_5 +# 31| r31_1(glval<_Complex float>) = VariableAddress[cf1] : +# 31| r31_2(_Complex float) = Load : &:r31_1, ~mu14_4 +# 31| r31_3(glval<_Complex float>) = VariableAddress[cf2] : +# 31| r31_4(_Complex float) = Load : &:r31_3, ~mu14_4 +# 31| r31_5(_Complex float) = Sub : r31_2, r31_4 +# 31| r31_6(glval<_Complex float>) = VariableAddress[cf3] : +# 31| mu31_7(_Complex float) = Store : &:r31_6, r31_5 +# 32| r32_1(glval<_Complex float>) = VariableAddress[cf1] : +# 32| r32_2(_Complex float) = Load : &:r32_1, ~mu14_4 +# 32| r32_3(glval<_Complex float>) = VariableAddress[cf2] : +# 32| r32_4(_Complex float) = Load : &:r32_3, ~mu14_4 +# 32| r32_5(_Complex float) = Mul : r32_2, r32_4 +# 32| r32_6(glval<_Complex float>) = VariableAddress[cf3] : +# 32| mu32_7(_Complex float) = Store : &:r32_6, r32_5 +# 33| r33_1(glval<_Complex float>) = VariableAddress[cf1] : +# 33| r33_2(_Complex float) = Load : &:r33_1, ~mu14_4 +# 33| r33_3(glval<_Complex float>) = VariableAddress[cf2] : +# 33| r33_4(_Complex float) = Load : &:r33_3, ~mu14_4 +# 33| r33_5(_Complex float) = Div : r33_2, r33_4 +# 33| r33_6(glval<_Complex float>) = VariableAddress[cf3] : +# 33| mu33_7(_Complex float) = Store : &:r33_6, r33_5 +# 36| r36_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 36| r36_2(_Imaginary float) = Load : &:r36_1, ~mu14_4 +# 36| r36_3(_Imaginary float) = CopyValue : r36_2 +# 36| r36_4(glval<_Imaginary float>) = VariableAddress[jf3] : +# 36| mu36_5(_Imaginary float) = Store : &:r36_4, r36_3 +# 37| r37_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 37| r37_2(_Imaginary float) = Load : &:r37_1, ~mu14_4 +# 37| r37_3(_Imaginary float) = Negate : r37_2 +# 37| r37_4(glval<_Imaginary float>) = VariableAddress[jf3] : +# 37| mu37_5(_Imaginary float) = Store : &:r37_4, r37_3 +# 40| r40_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 40| r40_2(_Imaginary float) = Load : &:r40_1, ~mu14_4 +# 40| r40_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 40| r40_4(_Imaginary float) = Load : &:r40_3, ~mu14_4 +# 40| r40_5(_Imaginary float) = Add : r40_2, r40_4 +# 40| r40_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 40| mu40_7(_Imaginary float) = Store : &:r40_6, r40_5 +# 41| r41_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 41| r41_2(_Imaginary float) = Load : &:r41_1, ~mu14_4 +# 41| r41_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 41| r41_4(_Imaginary float) = Load : &:r41_3, ~mu14_4 +# 41| r41_5(_Imaginary float) = Sub : r41_2, r41_4 +# 41| r41_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 41| mu41_7(_Imaginary float) = Store : &:r41_6, r41_5 +# 42| r42_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 42| r42_2(_Imaginary float) = Load : &:r42_1, ~mu14_4 +# 42| r42_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 42| r42_4(_Imaginary float) = Load : &:r42_3, ~mu14_4 +# 42| r42_5(float) = Mul : r42_2, r42_4 +# 42| r42_6(glval) = VariableAddress[f3] : +# 42| mu42_7(float) = Store : &:r42_6, r42_5 +# 43| r43_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 43| r43_2(_Imaginary float) = Load : &:r43_1, ~mu14_4 +# 43| r43_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 43| r43_4(_Imaginary float) = Load : &:r43_3, ~mu14_4 +# 43| r43_5(float) = Div : r43_2, r43_4 +# 43| r43_6(glval) = VariableAddress[f3] : +# 43| mu43_7(float) = Store : &:r43_6, r43_5 +# 46| r46_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 46| r46_2(_Imaginary float) = Load : &:r46_1, ~mu14_4 +# 46| r46_3(glval) = VariableAddress[f2] : +# 46| r46_4(float) = Load : &:r46_3, ~mu14_4 +# 46| r46_5(_Complex float) = Add : r46_2, r46_4 +# 46| r46_6(glval<_Complex float>) = VariableAddress[cf3] : +# 46| mu46_7(_Complex float) = Store : &:r46_6, r46_5 +# 47| r47_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 47| r47_2(_Imaginary float) = Load : &:r47_1, ~mu14_4 +# 47| r47_3(glval) = VariableAddress[f2] : +# 47| r47_4(float) = Load : &:r47_3, ~mu14_4 +# 47| r47_5(_Complex float) = Sub : r47_2, r47_4 +# 47| r47_6(glval<_Complex float>) = VariableAddress[cf3] : +# 47| mu47_7(_Complex float) = Store : &:r47_6, r47_5 +# 48| r48_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 48| r48_2(_Imaginary float) = Load : &:r48_1, ~mu14_4 +# 48| r48_3(glval) = VariableAddress[f2] : +# 48| r48_4(float) = Load : &:r48_3, ~mu14_4 +# 48| r48_5(_Imaginary float) = Mul : r48_2, r48_4 +# 48| r48_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 48| mu48_7(_Imaginary float) = Store : &:r48_6, r48_5 +# 49| r49_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 49| r49_2(_Imaginary float) = Load : &:r49_1, ~mu14_4 +# 49| r49_3(glval) = VariableAddress[f2] : +# 49| r49_4(float) = Load : &:r49_3, ~mu14_4 +# 49| r49_5(_Imaginary float) = Div : r49_2, r49_4 +# 49| r49_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 49| mu49_7(_Imaginary float) = Store : &:r49_6, r49_5 +# 52| r52_1(glval) = VariableAddress[f1] : +# 52| r52_2(float) = Load : &:r52_1, ~mu14_4 +# 52| r52_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 52| r52_4(_Imaginary float) = Load : &:r52_3, ~mu14_4 +# 52| r52_5(_Complex float) = Add : r52_2, r52_4 +# 52| r52_6(glval<_Complex float>) = VariableAddress[cf3] : +# 52| mu52_7(_Complex float) = Store : &:r52_6, r52_5 +# 53| r53_1(glval) = VariableAddress[f1] : +# 53| r53_2(float) = Load : &:r53_1, ~mu14_4 +# 53| r53_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 53| r53_4(_Imaginary float) = Load : &:r53_3, ~mu14_4 +# 53| r53_5(_Complex float) = Sub : r53_2, r53_4 +# 53| r53_6(glval<_Complex float>) = VariableAddress[cf3] : +# 53| mu53_7(_Complex float) = Store : &:r53_6, r53_5 +# 54| r54_1(glval) = VariableAddress[f1] : +# 54| r54_2(float) = Load : &:r54_1, ~mu14_4 +# 54| r54_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 54| r54_4(_Imaginary float) = Load : &:r54_3, ~mu14_4 +# 54| r54_5(_Imaginary float) = Mul : r54_2, r54_4 +# 54| r54_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 54| mu54_7(_Imaginary float) = Store : &:r54_6, r54_5 +# 55| r55_1(glval) = VariableAddress[f1] : +# 55| r55_2(float) = Load : &:r55_1, ~mu14_4 +# 55| r55_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 55| r55_4(_Imaginary float) = Load : &:r55_3, ~mu14_4 +# 55| r55_5(_Imaginary float) = Div : r55_2, r55_4 +# 55| r55_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 55| mu55_7(_Imaginary float) = Store : &:r55_6, r55_5 +# 56| v56_1(void) = NoOp : +# 14| v14_5(void) = ReturnVoid : +# 14| v14_6(void) = UnmodeledUse : mu* +# 14| v14_7(void) = AliasedUse : ~mu14_4 +# 14| v14_8(void) = ExitFunction : + +# 58| void complex_conversions() +# 58| Block 0 +# 58| v58_1(void) = EnterFunction : +# 58| mu58_2(unknown) = AliasedDefinition : +# 58| mu58_3(unknown) = InitializeNonLocal : +# 58| mu58_4(unknown) = UnmodeledDefinition : +# 59| r59_1(glval) = VariableAddress[f] : +# 59| r59_2(float) = Constant[2.0] : +# 59| mu59_3(float) = Store : &:r59_1, r59_2 +# 60| r60_1(glval) = VariableAddress[d] : +# 60| r60_2(double) = Constant[3.0] : +# 60| mu60_3(double) = Store : &:r60_1, r60_2 +# 61| r61_1(glval) = VariableAddress[ld] : +# 61| r61_2(long double) = Constant[5.0] : +# 61| mu61_3(long double) = Store : &:r61_1, r61_2 +# 62| r62_1(glval<_Complex float>) = VariableAddress[cf] : +# 62| r62_2(double) = Constant[7.0] : +# 62| r62_3(_Complex float) = Convert : r62_2 +# 62| mu62_4(_Complex float) = Store : &:r62_1, r62_3 +# 63| r63_1(glval<_Complex double>) = VariableAddress[cd] : +# 63| r63_2(double) = Constant[11.0] : +# 63| r63_3(_Complex double) = Convert : r63_2 +# 63| mu63_4(_Complex double) = Store : &:r63_1, r63_3 +# 64| r64_1(glval<_Complex long double>) = VariableAddress[cld] : +# 64| r64_2(double) = Constant[13.0] : +# 64| r64_3(_Complex long double) = Convert : r64_2 +# 64| mu64_4(_Complex long double) = Store : &:r64_1, r64_3 +# 65| r65_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 65| r65_2(_Imaginary float) = Constant[1.0i] : +# 65| mu65_3(_Imaginary float) = Store : &:r65_1, r65_2 +# 66| r66_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 66| r66_2(_Imaginary float) = Constant[1.0i] : +# 66| r66_3(_Imaginary double) = Convert : r66_2 +# 66| mu66_4(_Imaginary double) = Store : &:r66_1, r66_3 +# 67| r67_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 67| r67_2(_Imaginary float) = Constant[1.0i] : +# 67| r67_3(_Imaginary long double) = Convert : r67_2 +# 67| mu67_4(_Imaginary long double) = Store : &:r67_1, r67_3 +# 70| r70_1(glval<_Complex float>) = VariableAddress[cf] : +# 70| r70_2(_Complex float) = Load : &:r70_1, ~mu58_4 +# 70| r70_3(glval<_Complex float>) = VariableAddress[cf] : +# 70| mu70_4(_Complex float) = Store : &:r70_3, r70_2 +# 71| r71_1(glval<_Complex double>) = VariableAddress[cd] : +# 71| r71_2(_Complex double) = Load : &:r71_1, ~mu58_4 +# 71| r71_3(_Complex float) = Convert : r71_2 +# 71| r71_4(glval<_Complex float>) = VariableAddress[cf] : +# 71| mu71_5(_Complex float) = Store : &:r71_4, r71_3 +# 72| r72_1(glval<_Complex long double>) = VariableAddress[cld] : +# 72| r72_2(_Complex long double) = Load : &:r72_1, ~mu58_4 +# 72| r72_3(_Complex float) = Convert : r72_2 +# 72| r72_4(glval<_Complex float>) = VariableAddress[cf] : +# 72| mu72_5(_Complex float) = Store : &:r72_4, r72_3 +# 73| r73_1(glval<_Complex float>) = VariableAddress[cf] : +# 73| r73_2(_Complex float) = Load : &:r73_1, ~mu58_4 +# 73| r73_3(_Complex double) = Convert : r73_2 +# 73| r73_4(glval<_Complex double>) = VariableAddress[cd] : +# 73| mu73_5(_Complex double) = Store : &:r73_4, r73_3 +# 74| r74_1(glval<_Complex double>) = VariableAddress[cd] : +# 74| r74_2(_Complex double) = Load : &:r74_1, ~mu58_4 +# 74| r74_3(glval<_Complex double>) = VariableAddress[cd] : +# 74| mu74_4(_Complex double) = Store : &:r74_3, r74_2 +# 75| r75_1(glval<_Complex long double>) = VariableAddress[cld] : +# 75| r75_2(_Complex long double) = Load : &:r75_1, ~mu58_4 +# 75| r75_3(_Complex double) = Convert : r75_2 +# 75| r75_4(glval<_Complex double>) = VariableAddress[cd] : +# 75| mu75_5(_Complex double) = Store : &:r75_4, r75_3 +# 76| r76_1(glval<_Complex float>) = VariableAddress[cf] : +# 76| r76_2(_Complex float) = Load : &:r76_1, ~mu58_4 +# 76| r76_3(_Complex long double) = Convert : r76_2 +# 76| r76_4(glval<_Complex long double>) = VariableAddress[cld] : +# 76| mu76_5(_Complex long double) = Store : &:r76_4, r76_3 +# 77| r77_1(glval<_Complex double>) = VariableAddress[cd] : +# 77| r77_2(_Complex double) = Load : &:r77_1, ~mu58_4 +# 77| r77_3(_Complex long double) = Convert : r77_2 +# 77| r77_4(glval<_Complex long double>) = VariableAddress[cld] : +# 77| mu77_5(_Complex long double) = Store : &:r77_4, r77_3 +# 78| r78_1(glval<_Complex long double>) = VariableAddress[cld] : +# 78| r78_2(_Complex long double) = Load : &:r78_1, ~mu58_4 +# 78| r78_3(glval<_Complex long double>) = VariableAddress[cld] : +# 78| mu78_4(_Complex long double) = Store : &:r78_3, r78_2 +# 81| r81_1(glval) = VariableAddress[f] : +# 81| r81_2(float) = Load : &:r81_1, ~mu58_4 +# 81| r81_3(_Complex float) = Convert : r81_2 +# 81| r81_4(glval<_Complex float>) = VariableAddress[cf] : +# 81| mu81_5(_Complex float) = Store : &:r81_4, r81_3 +# 82| r82_1(glval) = VariableAddress[d] : +# 82| r82_2(double) = Load : &:r82_1, ~mu58_4 +# 82| r82_3(_Complex float) = Convert : r82_2 +# 82| r82_4(glval<_Complex float>) = VariableAddress[cf] : +# 82| mu82_5(_Complex float) = Store : &:r82_4, r82_3 +# 83| r83_1(glval) = VariableAddress[ld] : +# 83| r83_2(long double) = Load : &:r83_1, ~mu58_4 +# 83| r83_3(_Complex float) = Convert : r83_2 +# 83| r83_4(glval<_Complex float>) = VariableAddress[cf] : +# 83| mu83_5(_Complex float) = Store : &:r83_4, r83_3 +# 84| r84_1(glval) = VariableAddress[f] : +# 84| r84_2(float) = Load : &:r84_1, ~mu58_4 +# 84| r84_3(_Complex double) = Convert : r84_2 +# 84| r84_4(glval<_Complex double>) = VariableAddress[cd] : +# 84| mu84_5(_Complex double) = Store : &:r84_4, r84_3 +# 85| r85_1(glval) = VariableAddress[d] : +# 85| r85_2(double) = Load : &:r85_1, ~mu58_4 +# 85| r85_3(_Complex double) = Convert : r85_2 +# 85| r85_4(glval<_Complex double>) = VariableAddress[cd] : +# 85| mu85_5(_Complex double) = Store : &:r85_4, r85_3 +# 86| r86_1(glval) = VariableAddress[ld] : +# 86| r86_2(long double) = Load : &:r86_1, ~mu58_4 +# 86| r86_3(_Complex double) = Convert : r86_2 +# 86| r86_4(glval<_Complex double>) = VariableAddress[cd] : +# 86| mu86_5(_Complex double) = Store : &:r86_4, r86_3 +# 87| r87_1(glval) = VariableAddress[f] : +# 87| r87_2(float) = Load : &:r87_1, ~mu58_4 +# 87| r87_3(_Complex long double) = Convert : r87_2 +# 87| r87_4(glval<_Complex long double>) = VariableAddress[cld] : +# 87| mu87_5(_Complex long double) = Store : &:r87_4, r87_3 +# 88| r88_1(glval) = VariableAddress[d] : +# 88| r88_2(double) = Load : &:r88_1, ~mu58_4 +# 88| r88_3(_Complex long double) = Convert : r88_2 +# 88| r88_4(glval<_Complex long double>) = VariableAddress[cld] : +# 88| mu88_5(_Complex long double) = Store : &:r88_4, r88_3 +# 89| r89_1(glval) = VariableAddress[ld] : +# 89| r89_2(long double) = Load : &:r89_1, ~mu58_4 +# 89| r89_3(_Complex long double) = Convert : r89_2 +# 89| r89_4(glval<_Complex long double>) = VariableAddress[cld] : +# 89| mu89_5(_Complex long double) = Store : &:r89_4, r89_3 +# 92| r92_1(glval<_Complex float>) = VariableAddress[cf] : +# 92| r92_2(_Complex float) = Load : &:r92_1, ~mu58_4 +# 92| r92_3(float) = Convert : r92_2 +# 92| r92_4(glval) = VariableAddress[f] : +# 92| mu92_5(float) = Store : &:r92_4, r92_3 +# 93| r93_1(glval<_Complex double>) = VariableAddress[cd] : +# 93| r93_2(_Complex double) = Load : &:r93_1, ~mu58_4 +# 93| r93_3(float) = Convert : r93_2 +# 93| r93_4(glval) = VariableAddress[f] : +# 93| mu93_5(float) = Store : &:r93_4, r93_3 +# 94| r94_1(glval<_Complex long double>) = VariableAddress[cld] : +# 94| r94_2(_Complex long double) = Load : &:r94_1, ~mu58_4 +# 94| r94_3(float) = Convert : r94_2 +# 94| r94_4(glval) = VariableAddress[f] : +# 94| mu94_5(float) = Store : &:r94_4, r94_3 +# 95| r95_1(glval<_Complex float>) = VariableAddress[cf] : +# 95| r95_2(_Complex float) = Load : &:r95_1, ~mu58_4 +# 95| r95_3(double) = Convert : r95_2 +# 95| r95_4(glval) = VariableAddress[d] : +# 95| mu95_5(double) = Store : &:r95_4, r95_3 +# 96| r96_1(glval<_Complex double>) = VariableAddress[cd] : +# 96| r96_2(_Complex double) = Load : &:r96_1, ~mu58_4 +# 96| r96_3(double) = Convert : r96_2 +# 96| r96_4(glval) = VariableAddress[d] : +# 96| mu96_5(double) = Store : &:r96_4, r96_3 +# 97| r97_1(glval<_Complex long double>) = VariableAddress[cld] : +# 97| r97_2(_Complex long double) = Load : &:r97_1, ~mu58_4 +# 97| r97_3(double) = Convert : r97_2 +# 97| r97_4(glval) = VariableAddress[d] : +# 97| mu97_5(double) = Store : &:r97_4, r97_3 +# 98| r98_1(glval<_Complex float>) = VariableAddress[cf] : +# 98| r98_2(_Complex float) = Load : &:r98_1, ~mu58_4 +# 98| r98_3(long double) = Convert : r98_2 +# 98| r98_4(glval) = VariableAddress[ld] : +# 98| mu98_5(long double) = Store : &:r98_4, r98_3 +# 99| r99_1(glval<_Complex double>) = VariableAddress[cd] : +# 99| r99_2(_Complex double) = Load : &:r99_1, ~mu58_4 +# 99| r99_3(long double) = Convert : r99_2 +# 99| r99_4(glval) = VariableAddress[ld] : +# 99| mu99_5(long double) = Store : &:r99_4, r99_3 +# 100| r100_1(glval<_Complex long double>) = VariableAddress[cld] : +# 100| r100_2(_Complex long double) = Load : &:r100_1, ~mu58_4 +# 100| r100_3(long double) = Convert : r100_2 +# 100| r100_4(glval) = VariableAddress[ld] : +# 100| mu100_5(long double) = Store : &:r100_4, r100_3 +# 103| r103_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 103| r103_2(_Imaginary float) = Load : &:r103_1, ~mu58_4 +# 103| r103_3(_Complex float) = Convert : r103_2 +# 103| r103_4(glval<_Complex float>) = VariableAddress[cf] : +# 103| mu103_5(_Complex float) = Store : &:r103_4, r103_3 +# 104| r104_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 104| r104_2(_Imaginary double) = Load : &:r104_1, ~mu58_4 +# 104| r104_3(_Complex float) = Convert : r104_2 +# 104| r104_4(glval<_Complex float>) = VariableAddress[cf] : +# 104| mu104_5(_Complex float) = Store : &:r104_4, r104_3 +# 105| r105_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 105| r105_2(_Imaginary long double) = Load : &:r105_1, ~mu58_4 +# 105| r105_3(_Complex float) = Convert : r105_2 +# 105| r105_4(glval<_Complex float>) = VariableAddress[cf] : +# 105| mu105_5(_Complex float) = Store : &:r105_4, r105_3 +# 106| r106_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 106| r106_2(_Imaginary float) = Load : &:r106_1, ~mu58_4 +# 106| r106_3(_Complex double) = Convert : r106_2 +# 106| r106_4(glval<_Complex double>) = VariableAddress[cd] : +# 106| mu106_5(_Complex double) = Store : &:r106_4, r106_3 +# 107| r107_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 107| r107_2(_Imaginary double) = Load : &:r107_1, ~mu58_4 +# 107| r107_3(_Complex double) = Convert : r107_2 +# 107| r107_4(glval<_Complex double>) = VariableAddress[cd] : +# 107| mu107_5(_Complex double) = Store : &:r107_4, r107_3 +# 108| r108_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 108| r108_2(_Imaginary long double) = Load : &:r108_1, ~mu58_4 +# 108| r108_3(_Complex double) = Convert : r108_2 +# 108| r108_4(glval<_Complex double>) = VariableAddress[cd] : +# 108| mu108_5(_Complex double) = Store : &:r108_4, r108_3 +# 109| r109_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 109| r109_2(_Imaginary float) = Load : &:r109_1, ~mu58_4 +# 109| r109_3(_Complex long double) = Convert : r109_2 +# 109| r109_4(glval<_Complex long double>) = VariableAddress[cld] : +# 109| mu109_5(_Complex long double) = Store : &:r109_4, r109_3 +# 110| r110_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 110| r110_2(_Imaginary double) = Load : &:r110_1, ~mu58_4 +# 110| r110_3(_Complex long double) = Convert : r110_2 +# 110| r110_4(glval<_Complex long double>) = VariableAddress[cld] : +# 110| mu110_5(_Complex long double) = Store : &:r110_4, r110_3 +# 111| r111_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 111| r111_2(_Imaginary long double) = Load : &:r111_1, ~mu58_4 +# 111| r111_3(_Complex long double) = Convert : r111_2 +# 111| r111_4(glval<_Complex long double>) = VariableAddress[cld] : +# 111| mu111_5(_Complex long double) = Store : &:r111_4, r111_3 +# 114| r114_1(glval<_Complex float>) = VariableAddress[cf] : +# 114| r114_2(_Complex float) = Load : &:r114_1, ~mu58_4 +# 114| r114_3(_Imaginary float) = Convert : r114_2 +# 114| r114_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 114| mu114_5(_Imaginary float) = Store : &:r114_4, r114_3 +# 115| r115_1(glval<_Complex double>) = VariableAddress[cd] : +# 115| r115_2(_Complex double) = Load : &:r115_1, ~mu58_4 +# 115| r115_3(_Imaginary float) = Convert : r115_2 +# 115| r115_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 115| mu115_5(_Imaginary float) = Store : &:r115_4, r115_3 +# 116| r116_1(glval<_Complex long double>) = VariableAddress[cld] : +# 116| r116_2(_Complex long double) = Load : &:r116_1, ~mu58_4 +# 116| r116_3(_Imaginary float) = Convert : r116_2 +# 116| r116_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 116| mu116_5(_Imaginary float) = Store : &:r116_4, r116_3 +# 117| r117_1(glval<_Complex float>) = VariableAddress[cf] : +# 117| r117_2(_Complex float) = Load : &:r117_1, ~mu58_4 +# 117| r117_3(_Imaginary double) = Convert : r117_2 +# 117| r117_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 117| mu117_5(_Imaginary double) = Store : &:r117_4, r117_3 +# 118| r118_1(glval<_Complex double>) = VariableAddress[cd] : +# 118| r118_2(_Complex double) = Load : &:r118_1, ~mu58_4 +# 118| r118_3(_Imaginary double) = Convert : r118_2 +# 118| r118_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 118| mu118_5(_Imaginary double) = Store : &:r118_4, r118_3 +# 119| r119_1(glval<_Complex long double>) = VariableAddress[cld] : +# 119| r119_2(_Complex long double) = Load : &:r119_1, ~mu58_4 +# 119| r119_3(_Imaginary double) = Convert : r119_2 +# 119| r119_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 119| mu119_5(_Imaginary double) = Store : &:r119_4, r119_3 +# 120| r120_1(glval<_Complex float>) = VariableAddress[cf] : +# 120| r120_2(_Complex float) = Load : &:r120_1, ~mu58_4 +# 120| r120_3(_Imaginary long double) = Convert : r120_2 +# 120| r120_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 120| mu120_5(_Imaginary long double) = Store : &:r120_4, r120_3 +# 121| r121_1(glval<_Complex double>) = VariableAddress[cd] : +# 121| r121_2(_Complex double) = Load : &:r121_1, ~mu58_4 +# 121| r121_3(_Imaginary long double) = Convert : r121_2 +# 121| r121_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 121| mu121_5(_Imaginary long double) = Store : &:r121_4, r121_3 +# 122| r122_1(glval<_Complex long double>) = VariableAddress[cld] : +# 122| r122_2(_Complex long double) = Load : &:r122_1, ~mu58_4 +# 122| r122_3(_Imaginary long double) = Convert : r122_2 +# 122| r122_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 122| mu122_5(_Imaginary long double) = Store : &:r122_4, r122_3 +# 125| r125_1(glval) = VariableAddress[f] : +# 125| r125_2(float) = Load : &:r125_1, ~mu58_4 +# 125| r125_3(_Imaginary float) = Convert : r125_2 +# 125| r125_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 125| mu125_5(_Imaginary float) = Store : &:r125_4, r125_3 +# 126| r126_1(glval) = VariableAddress[d] : +# 126| r126_2(double) = Load : &:r126_1, ~mu58_4 +# 126| r126_3(_Imaginary float) = Convert : r126_2 +# 126| r126_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 126| mu126_5(_Imaginary float) = Store : &:r126_4, r126_3 +# 127| r127_1(glval) = VariableAddress[ld] : +# 127| r127_2(long double) = Load : &:r127_1, ~mu58_4 +# 127| r127_3(_Imaginary float) = Convert : r127_2 +# 127| r127_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 127| mu127_5(_Imaginary float) = Store : &:r127_4, r127_3 +# 128| r128_1(glval) = VariableAddress[f] : +# 128| r128_2(float) = Load : &:r128_1, ~mu58_4 +# 128| r128_3(_Imaginary double) = Convert : r128_2 +# 128| r128_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 128| mu128_5(_Imaginary double) = Store : &:r128_4, r128_3 +# 129| r129_1(glval) = VariableAddress[d] : +# 129| r129_2(double) = Load : &:r129_1, ~mu58_4 +# 129| r129_3(_Imaginary double) = Convert : r129_2 +# 129| r129_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 129| mu129_5(_Imaginary double) = Store : &:r129_4, r129_3 +# 130| r130_1(glval) = VariableAddress[ld] : +# 130| r130_2(long double) = Load : &:r130_1, ~mu58_4 +# 130| r130_3(_Imaginary double) = Convert : r130_2 +# 130| r130_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 130| mu130_5(_Imaginary double) = Store : &:r130_4, r130_3 +# 131| r131_1(glval) = VariableAddress[f] : +# 131| r131_2(float) = Load : &:r131_1, ~mu58_4 +# 131| r131_3(_Imaginary long double) = Convert : r131_2 +# 131| r131_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 131| mu131_5(_Imaginary long double) = Store : &:r131_4, r131_3 +# 132| r132_1(glval) = VariableAddress[d] : +# 132| r132_2(double) = Load : &:r132_1, ~mu58_4 +# 132| r132_3(_Imaginary long double) = Convert : r132_2 +# 132| r132_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 132| mu132_5(_Imaginary long double) = Store : &:r132_4, r132_3 +# 133| r133_1(glval) = VariableAddress[ld] : +# 133| r133_2(long double) = Load : &:r133_1, ~mu58_4 +# 133| r133_3(_Imaginary long double) = Convert : r133_2 +# 133| r133_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 133| mu133_5(_Imaginary long double) = Store : &:r133_4, r133_3 +# 136| r136_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 136| r136_2(_Imaginary float) = Load : &:r136_1, ~mu58_4 +# 136| r136_3(float) = Convert : r136_2 +# 136| r136_4(glval) = VariableAddress[f] : +# 136| mu136_5(float) = Store : &:r136_4, r136_3 +# 137| r137_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 137| r137_2(_Imaginary double) = Load : &:r137_1, ~mu58_4 +# 137| r137_3(float) = Convert : r137_2 +# 137| r137_4(glval) = VariableAddress[f] : +# 137| mu137_5(float) = Store : &:r137_4, r137_3 +# 138| r138_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 138| r138_2(_Imaginary long double) = Load : &:r138_1, ~mu58_4 +# 138| r138_3(float) = Convert : r138_2 +# 138| r138_4(glval) = VariableAddress[f] : +# 138| mu138_5(float) = Store : &:r138_4, r138_3 +# 139| r139_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 139| r139_2(_Imaginary float) = Load : &:r139_1, ~mu58_4 +# 139| r139_3(double) = Convert : r139_2 +# 139| r139_4(glval) = VariableAddress[d] : +# 139| mu139_5(double) = Store : &:r139_4, r139_3 +# 140| r140_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 140| r140_2(_Imaginary double) = Load : &:r140_1, ~mu58_4 +# 140| r140_3(double) = Convert : r140_2 +# 140| r140_4(glval) = VariableAddress[d] : +# 140| mu140_5(double) = Store : &:r140_4, r140_3 +# 141| r141_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 141| r141_2(_Imaginary long double) = Load : &:r141_1, ~mu58_4 +# 141| r141_3(double) = Convert : r141_2 +# 141| r141_4(glval) = VariableAddress[d] : +# 141| mu141_5(double) = Store : &:r141_4, r141_3 +# 142| r142_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 142| r142_2(_Imaginary float) = Load : &:r142_1, ~mu58_4 +# 142| r142_3(long double) = Convert : r142_2 +# 142| r142_4(glval) = VariableAddress[ld] : +# 142| mu142_5(long double) = Store : &:r142_4, r142_3 +# 143| r143_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 143| r143_2(_Imaginary double) = Load : &:r143_1, ~mu58_4 +# 143| r143_3(long double) = Convert : r143_2 +# 143| r143_4(glval) = VariableAddress[ld] : +# 143| mu143_5(long double) = Store : &:r143_4, r143_3 +# 144| r144_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 144| r144_2(_Imaginary long double) = Load : &:r144_1, ~mu58_4 +# 144| r144_3(long double) = Convert : r144_2 +# 144| r144_4(glval) = VariableAddress[ld] : +# 144| mu144_5(long double) = Store : &:r144_4, r144_3 +# 145| v145_1(void) = NoOp : +# 58| v58_5(void) = ReturnVoid : +# 58| v58_6(void) = UnmodeledUse : mu* +# 58| v58_7(void) = AliasedUse : ~mu58_4 +# 58| v58_8(void) = ExitFunction : ir.cpp: # 1| void Constants() diff --git a/cpp/ql/test/library-tests/ir/types/complex.c b/cpp/ql/test/library-tests/ir/types/complex.c index 3766bde086a..450f5de9e65 100644 --- a/cpp/ql/test/library-tests/ir/types/complex.c +++ b/cpp/ql/test/library-tests/ir/types/complex.c @@ -2,5 +2,14 @@ void Complex(void) { _Complex float cf; //$irtype=cfloat8 _Complex double cd; //$irtype=cfloat16 _Complex long double cld; //$irtype=cfloat32 - // _Complex __float128 cf128; -} \ No newline at end of file + // _Complex __float128 cf128; +} + +void Imaginary(void) { + _Imaginary float jf; //$irtype=ifloat4 + _Imaginary double jd; //$irtype=ifloat8 + _Imaginary long double jld; //$irtype=ifloat16 + // _Imaginary __float128 jf128; +} + +// semmle-extractor-options: --microsoft --edg --c99 From ea0f6a367deb9ed2d250b4ca22803b129913d3e0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 09:50:08 +0200 Subject: [PATCH 440/459] refactor into maybePromisified predicate --- .../javascript/frameworks/NodeJSLib.qll | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index bf343b28603..d2f5bea3b65 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -586,6 +586,19 @@ module NodeJSLib { } } + /** + * Gets a possibly promisified (using `util.promisify`) version of the input `func`. + */ + DataFlow::SourceNode maybePromisified(DataFlow::SourceNode func) { + result = func + or + exists(DataFlow::CallNode promisify | + promisify = DataFlow::moduleMember("util", "promisify").getACall() + | + result = promisify and promisify.getArgument(0).getALocalSource() = func + ) + } + /** * A call to a method from module `child_process`. */ @@ -593,15 +606,7 @@ module NodeJSLib { string methodName; ChildProcessMethodCall() { - this = DataFlow::moduleMember("child_process", methodName).getACall() - or - exists(DataFlow::CallNode promisify | - promisify = DataFlow::moduleMember("util", "promisify").getACall() - | - this = promisify.getACall() and - promisify.getArgument(0).getALocalSource() = - DataFlow::moduleMember("child_process", methodName) - ) + this = maybePromisified(DataFlow::moduleMember("child_process", methodName)).getACall() } private DataFlow::Node getACommandArgument(boolean shell) { From eca98b42d212e06684fd7c20635cfcf848fd611e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 09:54:37 +0200 Subject: [PATCH 441/459] basic support for util.promisify for NodeJSFileSystemAccess --- .../javascript/frameworks/NodeJSLib.qll | 2 +- .../CWE-022/TaintedPath/TaintedPath.expected | 199 ++++++++++++++++++ .../CWE-022/TaintedPath/other-fs-libraries.js | 8 + 3 files changed, 208 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index d2f5bea3b65..3437aa09830 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -459,7 +459,7 @@ module NodeJSLib { private class NodeJSFileSystemAccess extends FileSystemAccess, DataFlow::CallNode { string methodName; - NodeJSFileSystemAccess() { this = fsModuleMember(methodName).getACall() } + NodeJSFileSystemAccess() { this = maybePromisified(fsModuleMember(methodName)).getACall() } /** * Gets the name of the called method. diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index fb4fcb3503e..914c2099868 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -2082,6 +2082,92 @@ nodes | other-fs-libraries.js:24:35:24:38 | path | | other-fs-libraries.js:24:35:24:38 | path | | other-fs-libraries.js:24:35:24:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | | tainted-require.js:7:19:7:37 | req.param("module") | | tainted-require.js:7:19:7:37 | req.param("module") | | tainted-require.js:7:19:7:37 | req.param("module") | @@ -5673,6 +5759,118 @@ edges | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:9:14:9:37 | url.par ... , true) | | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:9:14:9:37 | url.par ... , true) | | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:9:14:9:37 | url.par ... , true) | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | @@ -6572,6 +6770,7 @@ edges | other-fs-libraries.js:17:35:17:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:17:35:17:38 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | | other-fs-libraries.js:19:56:19:59 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:19:56:19:59 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | | other-fs-libraries.js:24:35:24:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:24:35:24:38 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | +| other-fs-libraries.js:40:35:40:38 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:40:35:40:38 | path | This path depends on $@. | other-fs-libraries.js:38:24:38:30 | req.url | a user-provided value | | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value | | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | a user-provided value | | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js index 611aac86f30..5eb1d0d6524 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js @@ -31,3 +31,11 @@ function getFsModule(special) { return require("original-fs"); } } + +var util = require("util"); + +http.createServer(function(req, res) { + var path = url.parse(req.url, true).query.path; + + util.promisify(fs.readFileSync)(path); // NOT OK +}); \ No newline at end of file From c36142f129e075dde82c4d82cc8a68d95f546ee9 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 16 Apr 2020 11:52:30 +0200 Subject: [PATCH 442/459] C#: Add data-flow test for collections --- .../dataflow/arrays/ArrayFlow.cs | 229 +++++++++++++++++ .../dataflow/arrays/ArrayFlow.expected | 235 ++++++++++++++++++ .../dataflow/arrays/ArrayFlow.ql | 23 ++ 3 files changed, 487 insertions(+) create mode 100644 csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.cs create mode 100644 csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected create mode 100644 csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.ql diff --git a/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.cs b/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.cs new file mode 100644 index 00000000000..37ae6c6d299 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.cs @@ -0,0 +1,229 @@ +// semmle-extractor-options: /r:System.Linq.dll +using System; +using System.Collections.Generic; +using System.Linq; + +public class A +{ + public void M1() + { + var a = new A(); + var @as = new[] { a }; + Sink(@as[0]); // flow + SinkElem(@as); // flow + Sink(First(@as)); // flow + } + + public void M2(A other) + { + var a = new A(); + var @as = new[] { other }; + Sink(@as[0]); // no flow + SinkElem(@as); // no flow + Sink(First(@as)); // no flow + } + + public void M3() + { + var a = new A(); + var @as = new A[1]; + @as[0] = a; + Sink(@as[0]); // flow + SinkElem(@as); // flow + Sink(First(@as)); // flow + } + + public void M4(A other) + { + var a = new A(); + var @as = new A[1]; + @as[0] = other; + Sink(@as[0]); // no flow + SinkElem(@as); // no flow + Sink(First(@as)); // no flow + } + + public void M5() + { + var a = new A(); + var list = new List(); + list[0] = a; + Sink(list[0]); // flow + SinkListElem(list); // flow + Sink(ListFirst(list)); // flow + } + + public void M6(A other) + { + var list = new List(); + list[0] = other; + Sink(list[0]); // no flow + SinkListElem(list); // no flow + Sink(ListFirst(list)); // no flow + } + + public void M7() + { + var a = new A(); + var list = new List() { a }; + Sink(list[0]); // flow + SinkListElem(list); // flow + Sink(ListFirst(list)); // flow + } + + public void M8(A other) + { + var list = new List() { other }; + Sink(list[0]); // no flow + SinkListElem(list); // no flow + Sink(ListFirst(list)); // no flow + } + + public void M9() + { + var a = new A(); + var list = new List(); + list.Add(a); + Sink(list[0]); // flow + SinkListElem(list); // flow + Sink(ListFirst(list)); // flow + } + + public void M10(A other) + { + var list = new List(); + list.Add(other); + Sink(list[0]); // no flow + SinkListElem(list); // no flow + Sink(ListFirst(list)); // no flow + } + + public void M11() + { + var a = new A(); + var dict = new Dictionary(); + dict[0] = a; + Sink(dict[0]); // flow + SinkDictValue(dict); // flow + Sink(DictFirstValueA(dict)); // flow + Sink(DictFirstValueB(dict)); // flow [MISSING] + Sink(DictFirstValueC(dict)); // flow + } + + public void M12(A other) + { + var dict = new Dictionary(); + dict[0] = other; + Sink(dict[0]); // no flow + SinkDictValue(dict); // no flow + Sink(DictFirstValueA(dict)); // no flow + Sink(DictFirstValueB(dict)); // no flow + Sink(DictFirstValueC(dict)); // no flow + } + + public void M13() + { + var a = new A(); + var dict = new Dictionary() { { 0, a } }; + Sink(dict[0]); // flow + SinkDictValue(dict); // flow + Sink(DictFirstValueA(dict)); // flow + Sink(DictFirstValueB(dict)); // flow [MISSING] + Sink(DictFirstValueC(dict)); // flow + } + + public void M14(A other) + { + var dict = new Dictionary() { { 0, other } }; + Sink(dict[0]); // no flow + SinkDictValue(dict); // no flow + Sink(DictFirstValueA(dict)); // no flow + Sink(DictFirstValueB(dict)); // no flow + Sink(DictFirstValueC(dict)); // no flow + } + + public void M15() + { + var a = new A(); + var dict = new Dictionary() { { a, 0 } }; + Sink(dict.Keys.First()); // flow [MISSING] + SinkDictKey(dict); // flow [MISSING] + Sink(DictFirstKeyA(dict)); // flow [MISSING] + Sink(DictFirstKeyB(dict)); // flow [MISSING] + } + + public void M16(A other) + { + var dict = new Dictionary() { { other, 0 } }; + Sink(dict.Keys.First()); // no flow + SinkDictKey(dict); // no flow + Sink(DictFirstKeyA(dict)); // no flow + Sink(DictFirstKeyB(dict)); // no flow + } + + public void M17() + { + var a = new A(); + var @as = new[] { a }; + foreach (var x in @as) + Sink(x); // flow + } + + public void M18(A other) + { + var @as = new[] { other }; + foreach (var x in @as) + Sink(x); // no flow + } + + public void M19() + { + var a = new A(); + var @as = new[] { a }; + var enumerator = @as.GetEnumerator(); + while (enumerator.MoveNext()) + Sink(enumerator.Current); // flow + } + + public void M20(A other) + { + var @as = new[] { other }; + var enumerator = @as.GetEnumerator(); + while (enumerator.MoveNext()) + Sink(enumerator.Current); // no flow + } + + public void M21() + { + var a = new A(); + var list = new List(); + list.Add(a); + var enumerator = list.GetEnumerator(); + while (enumerator.MoveNext()) + Sink(enumerator.Current); // flow [MISSING] + } + + public static void Sink(T t) { } + + public static void SinkElem(T[] ts) => Sink(ts[0]); + + public static void SinkListElem(IList list) => Sink(list[0]); + + public static void SinkDictValue(IDictionary dict) => Sink(dict[0]); + + public static void SinkDictKey(IDictionary dict) => Sink(dict.Keys.First()); + + public static T First(T[] ts) => ts[0]; + + public static T ListFirst(IList list) => list[0]; + + public static T DictFirstValueA(IDictionary dict) => dict[0]; + + public static T DictFirstValueB(IDictionary dict) => dict.First().Value; + + public static T DictFirstValueC(IDictionary dict) => dict.Values.First(); + + public static T DictFirstKeyA(IDictionary dict) => dict.Keys.First(); + + public static T DictFirstKeyB(IDictionary dict) => dict.First().Key; +} diff --git a/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected b/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected new file mode 100644 index 00000000000..9a0b41ef207 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected @@ -0,0 +1,235 @@ +edges +| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:12:14:12:19 | access to array element | +| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:13:18:13:20 | access to local variable as : A[] | +| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:14:20:14:22 | access to local variable as : A[] | +| ArrayFlow.cs:13:18:13:20 | access to local variable as : A[] | ArrayFlow.cs:208:40:208:41 | ts : A[] | +| ArrayFlow.cs:14:20:14:22 | access to local variable as : A[] | ArrayFlow.cs:14:14:14:23 | call to method First | +| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:31:14:31:19 | access to array element | +| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:32:18:32:20 | access to local variable as : A[] | +| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:33:20:33:22 | access to local variable as : A[] | +| ArrayFlow.cs:32:18:32:20 | access to local variable as : A[] | ArrayFlow.cs:208:40:208:41 | ts : A[] | +| ArrayFlow.cs:33:20:33:22 | access to local variable as : A[] | ArrayFlow.cs:33:14:33:23 | call to method First | +| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:51:14:51:20 | access to indexer | +| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:52:22:52:25 | access to local variable list : List | +| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:53:24:53:27 | access to local variable list : List | +| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:51:14:51:20 | access to indexer | +| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:52:22:52:25 | access to local variable list : List | +| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:53:24:53:27 | access to local variable list : List | +| ArrayFlow.cs:52:22:52:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | +| ArrayFlow.cs:53:24:53:27 | access to local variable list : List | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | +| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:60:14:60:20 | access to indexer | +| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:61:22:61:25 | access to local variable list : List | +| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:62:24:62:27 | access to local variable list : List | +| ArrayFlow.cs:61:22:61:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | +| ArrayFlow.cs:62:24:62:27 | access to local variable list : List | ArrayFlow.cs:62:14:62:28 | call to method ListFirst | +| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:69:14:69:20 | access to indexer | +| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:70:22:70:25 | access to local variable list : List | +| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:71:24:71:27 | access to local variable list : List | +| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:69:14:69:20 | access to indexer | +| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:70:22:70:25 | access to local variable list : List | +| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:71:24:71:27 | access to local variable list : List | +| ArrayFlow.cs:70:22:70:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | +| ArrayFlow.cs:71:24:71:27 | access to local variable list : List | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | +| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:77:14:77:20 | access to indexer | +| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:78:22:78:25 | access to local variable list : List | +| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:79:24:79:27 | access to local variable list : List | +| ArrayFlow.cs:78:22:78:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | +| ArrayFlow.cs:79:24:79:27 | access to local variable list : List | ArrayFlow.cs:79:14:79:28 | call to method ListFirst | +| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:87:14:87:20 | access to indexer | +| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:88:22:88:25 | access to local variable list : List | +| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:89:24:89:27 | access to local variable list : List | +| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:87:14:87:20 | access to indexer | +| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:88:22:88:25 | access to local variable list : List | +| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:89:24:89:27 | access to local variable list : List | +| ArrayFlow.cs:88:22:88:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | +| ArrayFlow.cs:89:24:89:27 | access to local variable list : List | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | +| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:96:14:96:20 | access to indexer | +| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:97:22:97:25 | access to local variable list : List | +| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:98:24:98:27 | access to local variable list : List | +| ArrayFlow.cs:97:22:97:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | +| ArrayFlow.cs:98:24:98:27 | access to local variable list : List | ArrayFlow.cs:98:14:98:28 | call to method ListFirst | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:106:14:106:20 | access to indexer | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:106:14:106:20 | access to indexer | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | +| ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | +| ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:117:14:117:20 | access to indexer | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | +| ArrayFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | +| ArrayFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:128:14:128:20 | access to indexer | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:128:14:128:20 | access to indexer | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | +| ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | +| ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:138:14:138:20 | access to indexer | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | +| ArrayFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | +| ArrayFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | +| ArrayFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | +| ArrayFlow.cs:166:17:166:23 | object creation of type A : A | ArrayFlow.cs:169:18:169:18 | access to local variable x | +| ArrayFlow.cs:181:17:181:23 | object creation of type A : A | ArrayFlow.cs:185:18:185:35 | access to property Current | +| ArrayFlow.cs:208:40:208:41 | ts : A[] | ArrayFlow.cs:208:52:208:56 | access to array element | +| ArrayFlow.cs:210:49:210:52 | list : List | ArrayFlow.cs:210:63:210:69 | access to indexer | +| ArrayFlow.cs:212:61:212:64 | dict : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | +nodes +| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:12:14:12:19 | access to array element | semmle.label | access to array element | +| ArrayFlow.cs:13:18:13:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| ArrayFlow.cs:14:14:14:23 | call to method First | semmle.label | call to method First | +| ArrayFlow.cs:14:20:14:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:31:14:31:19 | access to array element | semmle.label | access to array element | +| ArrayFlow.cs:32:18:32:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| ArrayFlow.cs:33:14:33:23 | call to method First | semmle.label | call to method First | +| ArrayFlow.cs:33:20:33:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| ArrayFlow.cs:51:14:51:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:52:22:52:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:53:14:53:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| ArrayFlow.cs:53:24:53:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| ArrayFlow.cs:60:14:60:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:61:22:61:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:62:14:62:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| ArrayFlow.cs:62:24:62:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | semmle.label | object creation of type List : List | +| ArrayFlow.cs:69:14:69:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:70:22:70:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:71:14:71:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| ArrayFlow.cs:71:24:71:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | semmle.label | object creation of type List : List | +| ArrayFlow.cs:77:14:77:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:78:22:78:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:79:14:79:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| ArrayFlow.cs:79:24:79:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| ArrayFlow.cs:87:14:87:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:88:22:88:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:89:14:89:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| ArrayFlow.cs:89:24:89:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| ArrayFlow.cs:96:14:96:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:97:22:97:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:98:14:98:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| ArrayFlow.cs:98:24:98:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| ArrayFlow.cs:106:14:106:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| ArrayFlow.cs:117:14:117:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| ArrayFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| ArrayFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| ArrayFlow.cs:128:14:128:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| ArrayFlow.cs:138:14:138:20 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| ArrayFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| ArrayFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| ArrayFlow.cs:166:17:166:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:169:18:169:18 | access to local variable x | semmle.label | access to local variable x | +| ArrayFlow.cs:181:17:181:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| ArrayFlow.cs:185:18:185:35 | access to property Current | semmle.label | access to property Current | +| ArrayFlow.cs:208:40:208:41 | ts : A[] | semmle.label | ts : A[] | +| ArrayFlow.cs:208:52:208:56 | access to array element | semmle.label | access to array element | +| ArrayFlow.cs:210:49:210:52 | list : List | semmle.label | list : List | +| ArrayFlow.cs:210:63:210:69 | access to indexer | semmle.label | access to indexer | +| ArrayFlow.cs:212:61:212:64 | dict : Dictionary | semmle.label | dict : Dictionary | +| ArrayFlow.cs:212:75:212:81 | access to indexer | semmle.label | access to indexer | +#select +| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:12:14:12:19 | access to array element | $@ | ArrayFlow.cs:12:14:12:19 | access to array element | access to array element | +| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:14:14:14:23 | call to method First | $@ | ArrayFlow.cs:14:14:14:23 | call to method First | call to method First | +| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:208:52:208:56 | access to array element | $@ | ArrayFlow.cs:208:52:208:56 | access to array element | access to array element | +| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:31:14:31:19 | access to array element | $@ | ArrayFlow.cs:31:14:31:19 | access to array element | access to array element | +| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:33:14:33:23 | call to method First | $@ | ArrayFlow.cs:33:14:33:23 | call to method First | call to method First | +| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:208:52:208:56 | access to array element | $@ | ArrayFlow.cs:208:52:208:56 | access to array element | access to array element | +| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:51:14:51:20 | access to indexer | $@ | ArrayFlow.cs:51:14:51:20 | access to indexer | access to indexer | +| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | $@ | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:51:14:51:20 | access to indexer | $@ | ArrayFlow.cs:51:14:51:20 | access to indexer | access to indexer | +| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | $@ | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:60:14:60:20 | access to indexer | $@ | ArrayFlow.cs:60:14:60:20 | access to indexer | access to indexer | +| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:62:14:62:28 | call to method ListFirst | $@ | ArrayFlow.cs:62:14:62:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:69:14:69:20 | access to indexer | $@ | ArrayFlow.cs:69:14:69:20 | access to indexer | access to indexer | +| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | $@ | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:69:14:69:20 | access to indexer | $@ | ArrayFlow.cs:69:14:69:20 | access to indexer | access to indexer | +| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | $@ | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:77:14:77:20 | access to indexer | $@ | ArrayFlow.cs:77:14:77:20 | access to indexer | access to indexer | +| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:79:14:79:28 | call to method ListFirst | $@ | ArrayFlow.cs:79:14:79:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:87:14:87:20 | access to indexer | $@ | ArrayFlow.cs:87:14:87:20 | access to indexer | access to indexer | +| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | $@ | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:87:14:87:20 | access to indexer | $@ | ArrayFlow.cs:87:14:87:20 | access to indexer | access to indexer | +| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | $@ | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:96:14:96:20 | access to indexer | $@ | ArrayFlow.cs:96:14:96:20 | access to indexer | access to indexer | +| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:98:14:98:28 | call to method ListFirst | $@ | ArrayFlow.cs:98:14:98:28 | call to method ListFirst | call to method ListFirst | +| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:106:14:106:20 | access to indexer | $@ | ArrayFlow.cs:106:14:106:20 | access to indexer | access to indexer | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:106:14:106:20 | access to indexer | $@ | ArrayFlow.cs:106:14:106:20 | access to indexer | access to indexer | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:117:14:117:20 | access to indexer | $@ | ArrayFlow.cs:117:14:117:20 | access to indexer | access to indexer | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:128:14:128:20 | access to indexer | $@ | ArrayFlow.cs:128:14:128:20 | access to indexer | access to indexer | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:128:14:128:20 | access to indexer | $@ | ArrayFlow.cs:128:14:128:20 | access to indexer | access to indexer | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:138:14:138:20 | access to indexer | $@ | ArrayFlow.cs:138:14:138:20 | access to indexer | access to indexer | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| ArrayFlow.cs:166:17:166:23 | object creation of type A : A | ArrayFlow.cs:166:17:166:23 | object creation of type A : A | ArrayFlow.cs:169:18:169:18 | access to local variable x | $@ | ArrayFlow.cs:169:18:169:18 | access to local variable x | access to local variable x | +| ArrayFlow.cs:181:17:181:23 | object creation of type A : A | ArrayFlow.cs:181:17:181:23 | object creation of type A : A | ArrayFlow.cs:185:18:185:35 | access to property Current | $@ | ArrayFlow.cs:185:18:185:35 | access to property Current | access to property Current | diff --git a/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.ql b/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.ql new file mode 100644 index 00000000000..d1290562252 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.ql @@ -0,0 +1,23 @@ +/** + * @kind path-problem + */ + +import csharp +import DataFlow::PathGraph + +class Conf extends TaintTracking::Configuration { + Conf() { this = "ArrayFlowConf" } + + override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc | + mc.getTarget().hasName("Sink") and + mc.getAnArgument() = sink.asExpr() + ) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf +where conf.hasFlowPath(source, sink) +select source, source, sink, "$@", sink, sink.toString() From 427c32f2116ac9f8440dbe69540e7fc2ce53e185 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 11:25:23 +0200 Subject: [PATCH 443/459] report a local variable as the misspelling if there any many occourances of the global --- .../src/Expressions/MisspelledVariableName.ql | 37 +++++++++++++++++-- .../MisspelledVariableName.expected | 12 +++++- .../Expressions/MisspelledVariableName/tst.js | 12 ++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/Expressions/MisspelledVariableName.ql b/javascript/ql/src/Expressions/MisspelledVariableName.ql index ce5dc546341..9eeeb288134 100644 --- a/javascript/ql/src/Expressions/MisspelledVariableName.ql +++ b/javascript/ql/src/Expressions/MisspelledVariableName.ql @@ -14,6 +14,37 @@ import Misspelling -from GlobalVarAccess gva, VarDecl lvd -where misspelledVariableName(gva, lvd) -select gva, "'" + gva + "' may be a typo for variable $@.", lvd, lvd.getName() +/** + * Gets the number of times a local variable with name `name` occurs in the program. + */ +bindingset[name] +int localAcceses(string name) { + result = count(VarAccess acc | acc.getName() = name and not acc instanceof GlobalVarAccess) +} + +/** + * Gets the number of times a global variable with name `name` occurs in the program. + */ +bindingset[name] +int globalAccesses(string name) { result = count(GlobalVarAccess acc | acc.getName() = name) } + +/** + * Holds if our heuristic says that the local variable `lvd` seems to be a misspelling of the global variable `gvd`. + * Otherwise the global variable is likely the misspelling. + */ +predicate globalIsLikelyCorrect(GlobalVarAccess gva, VarDecl lvd) { + // If there are more occurrences of the global (by a margin of at least 2), and the local is missing one letter compared to the global. + globalAccesses(gva.getName()) >= localAcceses(lvd.getName()) + 2 and + lvd.getName().length() = gva.getName().length() - 1 + or + // Or if there are many more of the global. + globalAccesses(gva.getName()) > 2 * localAcceses(lvd.getName()) + 2 +} + +from GlobalVarAccess gva, VarDecl lvd, string msg +where + misspelledVariableName(gva, lvd) and + if globalIsLikelyCorrect(gva, lvd) + then msg = "$@ may be a typo for '" + gva + "'." + else msg = "'" + gva + "' may be a typo for variable $@." +select gva, msg, lvd, lvd.getName() diff --git a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected index 43098d60483..535682017e4 100644 --- a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected +++ b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected @@ -1,5 +1,13 @@ | MisspelledVariableName.js:2:40:2:45 | lenght | 'lenght' may be a typo for variable $@. | MisspelledVariableName.js:2:19:2:24 | length | length | | tst.js:2:10:2:20 | errorMesage | 'errorMesage' may be a typo for variable $@. | tst.js:1:12:1:23 | errorMessage | errorMessage | -| tst.js:6:10:6:21 | errorMessage | 'errorMessage' may be a typo for variable $@. | tst.js:5:12:5:22 | errorMesage | errorMesage | +| tst.js:6:10:6:21 | errorMessage | $@ may be a typo for 'errorMessage'. | tst.js:5:12:5:22 | errorMesage | errorMesage | | tst.js:11:12:11:22 | errorMesage | 'errorMesage' may be a typo for variable $@. | tst.js:9:12:9:23 | errorMessage | errorMessage | -| tst.js:17:5:17:16 | errorMessage | 'errorMessage' may be a typo for variable $@. | tst.js:15:12:15:22 | errorMesage | errorMesage | +| tst.js:17:5:17:16 | errorMessage | $@ may be a typo for 'errorMessage'. | tst.js:15:12:15:22 | errorMesage | errorMesage | +| tst.js:22:2:22:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:23:2:23:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:24:2:24:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:25:2:25:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:26:2:26:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:27:2:27:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:28:2:28:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:29:2:29:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | diff --git a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js index bc669b52957..cd6c027f1fc 100644 --- a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js +++ b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js @@ -16,3 +16,15 @@ function k(errorMesage) { let inner = () => errorMessage; } + +function foo() { + var thisHander; + thisHandler.foo1; + thisHandler.foo2; + thisHandler.foo3; + thisHandler.foo4; + thisHandler.foo5; + thisHandler.foo6; + thisHandler.foo7; + thisHandler.foo8; +} \ No newline at end of file From 4f32157a787b36cc34b91d654c3cf0b2b41551d7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 11:36:48 +0200 Subject: [PATCH 444/459] rename `func` to `callback` Co-Authored-By: Esben Sparre Andreasen --- .../ql/src/semmle/javascript/frameworks/NodeJSLib.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 3437aa09830..fadc30ded07 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -587,15 +587,15 @@ module NodeJSLib { } /** - * Gets a possibly promisified (using `util.promisify`) version of the input `func`. + * Gets a possibly promisified (using `util.promisify`) version of the input `callback`. */ - DataFlow::SourceNode maybePromisified(DataFlow::SourceNode func) { - result = func + DataFlow::SourceNode maybePromisified(DataFlow::SourceNode callback) { + result = callback or exists(DataFlow::CallNode promisify | promisify = DataFlow::moduleMember("util", "promisify").getACall() | - result = promisify and promisify.getArgument(0).getALocalSource() = func + result = promisify and promisify.getArgument(0).getALocalSource() = callback ) } From 3b230648d2de64a91a2a4dfec774c5ea86e70509 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 11:45:08 +0200 Subject: [PATCH 445/459] change-note --- change-notes/1.24/analysis-javascript.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index 0e92d66033d..b6ba0099c14 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -87,6 +87,8 @@ | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | | Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. | +| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes more file system calls. | +| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes more command execution calls. | ## Changes to libraries From 4a93b91d59391278cbd675a8c064166724b3e2dc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 11:47:03 +0200 Subject: [PATCH 446/459] make maybePromisified private --- javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index fadc30ded07..e368b16e433 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -589,7 +589,7 @@ module NodeJSLib { /** * Gets a possibly promisified (using `util.promisify`) version of the input `callback`. */ - DataFlow::SourceNode maybePromisified(DataFlow::SourceNode callback) { + private DataFlow::SourceNode maybePromisified(DataFlow::SourceNode callback) { result = callback or exists(DataFlow::CallNode promisify | From 8c03423f3e88e847a19a3ec0bfa873d334414601 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 17 Apr 2020 12:03:16 +0200 Subject: [PATCH 447/459] C++: Accept test output --- .../dataflow/dataflow-tests/test_diff.expected | 7 ------- .../library-tests/dataflow/dataflow-tests/test_ir.expected | 7 +++++++ .../library-tests/dataflow/taint-tests/test_diff.expected | 1 - .../library-tests/dataflow/taint-tests/test_ir.expected | 1 + 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 71630f892f5..9bad6e02bcc 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -31,10 +31,6 @@ | ref.cpp:53:17:53:18 | ref.cpp:62:10:62:11 | AST only | | ref.cpp:53:21:53:22 | ref.cpp:65:10:65:11 | AST only | | ref.cpp:55:23:55:28 | ref.cpp:56:10:56:11 | AST only | -| ref.cpp:94:15:94:20 | ref.cpp:129:13:129:15 | AST only | -| ref.cpp:109:15:109:20 | ref.cpp:132:13:132:15 | AST only | -| ref.cpp:122:23:122:28 | ref.cpp:123:13:123:15 | AST only | -| ref.cpp:125:19:125:24 | ref.cpp:126:13:126:15 | AST only | | test.cpp:75:7:75:8 | test.cpp:76:8:76:9 | AST only | | test.cpp:83:7:83:8 | test.cpp:84:8:84:18 | AST only | | test.cpp:83:7:83:8 | test.cpp:86:8:86:9 | AST only | @@ -45,9 +41,6 @@ | test.cpp:359:13:359:18 | test.cpp:365:10:365:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:369:10:369:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:375:10:375:14 | AST only | -| test.cpp:382:48:382:54 | test.cpp:385:8:385:10 | AST only | -| test.cpp:388:53:388:59 | test.cpp:392:8:392:10 | AST only | -| test.cpp:388:53:388:59 | test.cpp:394:10:394:12 | AST only | | test.cpp:399:7:399:9 | test.cpp:401:8:401:10 | AST only | | test.cpp:405:7:405:9 | test.cpp:408:8:408:10 | AST only | | test.cpp:416:7:416:11 | test.cpp:418:8:418:12 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 275cbabc075..35068c56232 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -39,6 +39,10 @@ | globals.cpp:12:10:12:24 | flowTestGlobal1 | globals.cpp:13:23:13:28 | call to source | | globals.cpp:19:10:19:24 | flowTestGlobal2 | globals.cpp:23:23:23:28 | call to source | | lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source | +| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source | +| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source | +| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source | +| ref.cpp:132:13:132:15 | val | ref.cpp:109:15:109:20 | call to source | | test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source | @@ -61,6 +65,9 @@ | test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source | | test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source | | test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source | +| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 | +| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 | +| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 | | test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 | | test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 | | true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | 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 af9d002dcdc..3be23cbcc40 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 @@ -28,7 +28,6 @@ | taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only | -| taint.cpp:216:7:216:7 | taint.cpp:207:6:207:11 | AST only | | taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | 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 9dc1088434c..b44e17882e7 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 @@ -12,6 +12,7 @@ | taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source | | taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source | +| taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source | | taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source | | taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source | | taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source | From e72eed1db5b9364104c5d72ceabe3c365f494473 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 13:10:06 +0200 Subject: [PATCH 448/459] more -> additional Co-Authored-By: Esben Sparre Andreasen --- change-notes/1.24/analysis-javascript.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index b6ba0099c14..e3f7e920848 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -86,9 +86,9 @@ | Useless regular-expression character escape (`js/useless-regexp-character-escape`) | Fewer false positive results | This query now distinguishes escapes in strings and regular expression literals. | | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | -| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. | -| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes more file system calls. | -| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes more command execution calls. | +| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional variations of URL scheme checks. | +| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. | +| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. | ## Changes to libraries From 225dc4b01790bb21e48643ff944eddca04067a13 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 13:54:48 +0200 Subject: [PATCH 449/459] change-note --- change-notes/1.24/analysis-javascript.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index 0e92d66033d..e2f7141c146 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -87,6 +87,7 @@ | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | | Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. | +| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in more cases. | ## Changes to libraries From 88f600fa3496dfc5e8baa534eb06e768f4cf3cbe Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 14:14:08 +0200 Subject: [PATCH 450/459] more -> additional Co-Authored-By: Esben Sparre Andreasen --- change-notes/1.24/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index e2f7141c146..bba72368168 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -87,7 +87,7 @@ | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | | Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. | -| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in more cases. | +| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. | ## Changes to libraries From a2ddf7bf8fc395274911a3a1d422829647b9dbb1 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 14:19:17 +0200 Subject: [PATCH 451/459] retarget change-note for 1.25 --- change-notes/1.24/analysis-javascript.md | 1 - change-notes/1.25/analysis-javascript.md | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 change-notes/1.25/analysis-javascript.md diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index bba72368168..0e92d66033d 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -87,7 +87,6 @@ | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | | Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. | -| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. | ## Changes to libraries diff --git a/change-notes/1.25/analysis-javascript.md b/change-notes/1.25/analysis-javascript.md new file mode 100644 index 00000000000..ee1c3c8ee3e --- /dev/null +++ b/change-notes/1.25/analysis-javascript.md @@ -0,0 +1,20 @@ +# Improvements to JavaScript analysis + +## General improvements + + +## New queries + +| **Query** | **Tags** | **Purpose** | +|---------------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| + + +## Changes to existing queries + +| **Query** | **Expected impact** | **Change** | +|--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. | + +## Changes to libraries + + From cffa9116618cd0786fce4c42c3bc935f817aaa43 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 17 Apr 2020 14:22:57 +0200 Subject: [PATCH 452/459] retarget change note for 1.25 --- change-notes/1.24/analysis-javascript.md | 2 -- change-notes/1.25/analysis-javascript.md | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 change-notes/1.25/analysis-javascript.md diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index e3f7e920848..c27f7850041 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -87,8 +87,6 @@ | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | | Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional variations of URL scheme checks. | -| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. | -| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. | ## Changes to libraries diff --git a/change-notes/1.25/analysis-javascript.md b/change-notes/1.25/analysis-javascript.md new file mode 100644 index 00000000000..e26ed8fee6f --- /dev/null +++ b/change-notes/1.25/analysis-javascript.md @@ -0,0 +1,22 @@ +# Improvements to JavaScript analysis + +## General improvements + + +## New queries + +| **Query** | **Tags** | **Purpose** | +|---------------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| + + +## Changes to existing queries + +| **Query** | **Expected impact** | **Change** | +|--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. | +| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. | + +## Changes to libraries + + + From de5abdb29a15a9980764a2ad740aa30348bbeebe Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Sat, 18 Apr 2020 09:55:35 -0400 Subject: [PATCH 453/459] C++/C#: Add missing QLDoc --- cpp/ql/src/semmle/code/cpp/Type.qll | 1 + .../ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll | 1 + 2 files changed, 2 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index f6787d00e1a..56e18fa055e 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -707,6 +707,7 @@ private newtype TTypeDomain = * `ImaginaryDomain`. */ class TypeDomain extends TTypeDomain { + /** Gets a textual representation of this type domain. */ string toString() { none() } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll index 24870f5635a..2272257fb19 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll @@ -35,6 +35,7 @@ private newtype TTypeDomain = TRealDomain() * `ImaginaryDomain`. */ class TypeDomain extends TTypeDomain { + /** Gets a textual representation of this type domain. */ string toString() { none() } } From 8041b74f1cf04b111ebe99f99f3d46537e7638bc Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Sat, 18 Apr 2020 09:56:38 -0400 Subject: [PATCH 454/459] C++: Fix formatting --- .../semmle/code/cpp/ir/internal/CppType.qll | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll index 42420f8f925..d297097abd9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll @@ -453,12 +453,19 @@ CppPRValueType getCanonicalUnsignedIntegerType(int byteSize) { */ private int getPrecisionPriority(RealNumberType type) { // Prefer `double`, `float`, `long double` in that order. - if type instanceof DoubleType then result = 4 - else if type instanceof FloatType then result = 3 - else if type instanceof LongDoubleType then result = 2 - // If we get this far, prefer non-extended-precision types. - else if not type.isExtendedPrecision() then result = 1 - else result = 0 + if type instanceof DoubleType + then result = 4 + else + if type instanceof FloatType + then result = 3 + else + if type instanceof LongDoubleType + then result = 2 + else + // If we get this far, prefer non-extended-precision types. + if not type.isExtendedPrecision() + then result = 1 + else result = 0 } /** From 161093bd57f1e5f4b0066a663c46b5575f8823d1 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 20 Apr 2020 09:20:42 +0200 Subject: [PATCH 455/459] C#: Rename `arrays` data-flow test to `collections` --- .../dataflow/arrays/ArrayFlow.expected | 235 ------------------ .../CollectionFlow.cs} | 0 .../collections/CollectionFlow.expected | 235 ++++++++++++++++++ .../CollectionFlow.ql} | 0 4 files changed, 235 insertions(+), 235 deletions(-) delete mode 100644 csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected rename csharp/ql/test/library-tests/dataflow/{arrays/ArrayFlow.cs => collections/CollectionFlow.cs} (100%) create mode 100644 csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected rename csharp/ql/test/library-tests/dataflow/{arrays/ArrayFlow.ql => collections/CollectionFlow.ql} (100%) diff --git a/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected b/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected deleted file mode 100644 index 9a0b41ef207..00000000000 --- a/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.expected +++ /dev/null @@ -1,235 +0,0 @@ -edges -| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:12:14:12:19 | access to array element | -| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:13:18:13:20 | access to local variable as : A[] | -| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:14:20:14:22 | access to local variable as : A[] | -| ArrayFlow.cs:13:18:13:20 | access to local variable as : A[] | ArrayFlow.cs:208:40:208:41 | ts : A[] | -| ArrayFlow.cs:14:20:14:22 | access to local variable as : A[] | ArrayFlow.cs:14:14:14:23 | call to method First | -| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:31:14:31:19 | access to array element | -| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:32:18:32:20 | access to local variable as : A[] | -| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:33:20:33:22 | access to local variable as : A[] | -| ArrayFlow.cs:32:18:32:20 | access to local variable as : A[] | ArrayFlow.cs:208:40:208:41 | ts : A[] | -| ArrayFlow.cs:33:20:33:22 | access to local variable as : A[] | ArrayFlow.cs:33:14:33:23 | call to method First | -| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:51:14:51:20 | access to indexer | -| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:52:22:52:25 | access to local variable list : List | -| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:53:24:53:27 | access to local variable list : List | -| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:51:14:51:20 | access to indexer | -| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:52:22:52:25 | access to local variable list : List | -| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:53:24:53:27 | access to local variable list : List | -| ArrayFlow.cs:52:22:52:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | -| ArrayFlow.cs:53:24:53:27 | access to local variable list : List | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | -| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:60:14:60:20 | access to indexer | -| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:61:22:61:25 | access to local variable list : List | -| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:62:24:62:27 | access to local variable list : List | -| ArrayFlow.cs:61:22:61:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | -| ArrayFlow.cs:62:24:62:27 | access to local variable list : List | ArrayFlow.cs:62:14:62:28 | call to method ListFirst | -| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:69:14:69:20 | access to indexer | -| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:70:22:70:25 | access to local variable list : List | -| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:71:24:71:27 | access to local variable list : List | -| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:69:14:69:20 | access to indexer | -| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:70:22:70:25 | access to local variable list : List | -| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:71:24:71:27 | access to local variable list : List | -| ArrayFlow.cs:70:22:70:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | -| ArrayFlow.cs:71:24:71:27 | access to local variable list : List | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | -| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:77:14:77:20 | access to indexer | -| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:78:22:78:25 | access to local variable list : List | -| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:79:24:79:27 | access to local variable list : List | -| ArrayFlow.cs:78:22:78:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | -| ArrayFlow.cs:79:24:79:27 | access to local variable list : List | ArrayFlow.cs:79:14:79:28 | call to method ListFirst | -| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:87:14:87:20 | access to indexer | -| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:88:22:88:25 | access to local variable list : List | -| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:89:24:89:27 | access to local variable list : List | -| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:87:14:87:20 | access to indexer | -| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:88:22:88:25 | access to local variable list : List | -| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:89:24:89:27 | access to local variable list : List | -| ArrayFlow.cs:88:22:88:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | -| ArrayFlow.cs:89:24:89:27 | access to local variable list : List | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | -| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:96:14:96:20 | access to indexer | -| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:97:22:97:25 | access to local variable list : List | -| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:98:24:98:27 | access to local variable list : List | -| ArrayFlow.cs:97:22:97:25 | access to local variable list : List | ArrayFlow.cs:210:49:210:52 | list : List | -| ArrayFlow.cs:98:24:98:27 | access to local variable list : List | ArrayFlow.cs:98:14:98:28 | call to method ListFirst | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:106:14:106:20 | access to indexer | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:106:14:106:20 | access to indexer | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | -| ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | -| ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:117:14:117:20 | access to indexer | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | -| ArrayFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | -| ArrayFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:128:14:128:20 | access to indexer | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:128:14:128:20 | access to indexer | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | -| ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | -| ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:138:14:138:20 | access to indexer | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | -| ArrayFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | ArrayFlow.cs:212:61:212:64 | dict : Dictionary | -| ArrayFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | -| ArrayFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | -| ArrayFlow.cs:166:17:166:23 | object creation of type A : A | ArrayFlow.cs:169:18:169:18 | access to local variable x | -| ArrayFlow.cs:181:17:181:23 | object creation of type A : A | ArrayFlow.cs:185:18:185:35 | access to property Current | -| ArrayFlow.cs:208:40:208:41 | ts : A[] | ArrayFlow.cs:208:52:208:56 | access to array element | -| ArrayFlow.cs:210:49:210:52 | list : List | ArrayFlow.cs:210:63:210:69 | access to indexer | -| ArrayFlow.cs:212:61:212:64 | dict : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | -nodes -| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:12:14:12:19 | access to array element | semmle.label | access to array element | -| ArrayFlow.cs:13:18:13:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| ArrayFlow.cs:14:14:14:23 | call to method First | semmle.label | call to method First | -| ArrayFlow.cs:14:20:14:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:31:14:31:19 | access to array element | semmle.label | access to array element | -| ArrayFlow.cs:32:18:32:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| ArrayFlow.cs:33:14:33:23 | call to method First | semmle.label | call to method First | -| ArrayFlow.cs:33:20:33:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| ArrayFlow.cs:51:14:51:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:52:22:52:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:53:14:53:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| ArrayFlow.cs:53:24:53:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| ArrayFlow.cs:60:14:60:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:61:22:61:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:62:14:62:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| ArrayFlow.cs:62:24:62:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | semmle.label | object creation of type List : List | -| ArrayFlow.cs:69:14:69:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:70:22:70:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:71:14:71:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| ArrayFlow.cs:71:24:71:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | semmle.label | object creation of type List : List | -| ArrayFlow.cs:77:14:77:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:78:22:78:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:79:14:79:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| ArrayFlow.cs:79:24:79:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| ArrayFlow.cs:87:14:87:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:88:22:88:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:89:14:89:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| ArrayFlow.cs:89:24:89:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| ArrayFlow.cs:96:14:96:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:97:22:97:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:98:14:98:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| ArrayFlow.cs:98:24:98:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| ArrayFlow.cs:106:14:106:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| ArrayFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| ArrayFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| ArrayFlow.cs:117:14:117:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| ArrayFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| ArrayFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| ArrayFlow.cs:128:14:128:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| ArrayFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| ArrayFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| ArrayFlow.cs:138:14:138:20 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| ArrayFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| ArrayFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| ArrayFlow.cs:166:17:166:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:169:18:169:18 | access to local variable x | semmle.label | access to local variable x | -| ArrayFlow.cs:181:17:181:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| ArrayFlow.cs:185:18:185:35 | access to property Current | semmle.label | access to property Current | -| ArrayFlow.cs:208:40:208:41 | ts : A[] | semmle.label | ts : A[] | -| ArrayFlow.cs:208:52:208:56 | access to array element | semmle.label | access to array element | -| ArrayFlow.cs:210:49:210:52 | list : List | semmle.label | list : List | -| ArrayFlow.cs:210:63:210:69 | access to indexer | semmle.label | access to indexer | -| ArrayFlow.cs:212:61:212:64 | dict : Dictionary | semmle.label | dict : Dictionary | -| ArrayFlow.cs:212:75:212:81 | access to indexer | semmle.label | access to indexer | -#select -| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:12:14:12:19 | access to array element | $@ | ArrayFlow.cs:12:14:12:19 | access to array element | access to array element | -| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:14:14:14:23 | call to method First | $@ | ArrayFlow.cs:14:14:14:23 | call to method First | call to method First | -| ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:10:17:10:23 | object creation of type A : A | ArrayFlow.cs:208:52:208:56 | access to array element | $@ | ArrayFlow.cs:208:52:208:56 | access to array element | access to array element | -| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:31:14:31:19 | access to array element | $@ | ArrayFlow.cs:31:14:31:19 | access to array element | access to array element | -| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:33:14:33:23 | call to method First | $@ | ArrayFlow.cs:33:14:33:23 | call to method First | call to method First | -| ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:28:17:28:23 | object creation of type A : A | ArrayFlow.cs:208:52:208:56 | access to array element | $@ | ArrayFlow.cs:208:52:208:56 | access to array element | access to array element | -| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:51:14:51:20 | access to indexer | $@ | ArrayFlow.cs:51:14:51:20 | access to indexer | access to indexer | -| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | $@ | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:48:17:48:23 | object creation of type A : A | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:51:14:51:20 | access to indexer | $@ | ArrayFlow.cs:51:14:51:20 | access to indexer | access to indexer | -| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | $@ | ArrayFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:49:20:49:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:60:14:60:20 | access to indexer | $@ | ArrayFlow.cs:60:14:60:20 | access to indexer | access to indexer | -| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:62:14:62:28 | call to method ListFirst | $@ | ArrayFlow.cs:62:14:62:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:58:20:58:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:69:14:69:20 | access to indexer | $@ | ArrayFlow.cs:69:14:69:20 | access to indexer | access to indexer | -| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | $@ | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:67:17:67:23 | object creation of type A : A | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:69:14:69:20 | access to indexer | $@ | ArrayFlow.cs:69:14:69:20 | access to indexer | access to indexer | -| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | $@ | ArrayFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:68:20:68:38 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:77:14:77:20 | access to indexer | $@ | ArrayFlow.cs:77:14:77:20 | access to indexer | access to indexer | -| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:79:14:79:28 | call to method ListFirst | $@ | ArrayFlow.cs:79:14:79:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:76:20:76:42 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:87:14:87:20 | access to indexer | $@ | ArrayFlow.cs:87:14:87:20 | access to indexer | access to indexer | -| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | $@ | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:84:17:84:23 | object creation of type A : A | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:87:14:87:20 | access to indexer | $@ | ArrayFlow.cs:87:14:87:20 | access to indexer | access to indexer | -| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | $@ | ArrayFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:85:20:85:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:96:14:96:20 | access to indexer | $@ | ArrayFlow.cs:96:14:96:20 | access to indexer | access to indexer | -| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:98:14:98:28 | call to method ListFirst | $@ | ArrayFlow.cs:98:14:98:28 | call to method ListFirst | call to method ListFirst | -| ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:94:20:94:32 | object creation of type List : List | ArrayFlow.cs:210:63:210:69 | access to indexer | $@ | ArrayFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:106:14:106:20 | access to indexer | $@ | ArrayFlow.cs:106:14:106:20 | access to indexer | access to indexer | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:103:17:103:23 | object creation of type A : A | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:106:14:106:20 | access to indexer | $@ | ArrayFlow.cs:106:14:106:20 | access to indexer | access to indexer | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:117:14:117:20 | access to indexer | $@ | ArrayFlow.cs:117:14:117:20 | access to indexer | access to indexer | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:119:14:119:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:121:14:121:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:128:14:128:20 | access to indexer | $@ | ArrayFlow.cs:128:14:128:20 | access to indexer | access to indexer | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:126:17:126:23 | object creation of type A : A | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:128:14:128:20 | access to indexer | $@ | ArrayFlow.cs:128:14:128:20 | access to indexer | access to indexer | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:138:14:138:20 | access to indexer | $@ | ArrayFlow.cs:138:14:138:20 | access to indexer | access to indexer | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | $@ | ArrayFlow.cs:140:14:140:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | $@ | ArrayFlow.cs:142:14:142:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | ArrayFlow.cs:212:75:212:81 | access to indexer | $@ | ArrayFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| ArrayFlow.cs:166:17:166:23 | object creation of type A : A | ArrayFlow.cs:166:17:166:23 | object creation of type A : A | ArrayFlow.cs:169:18:169:18 | access to local variable x | $@ | ArrayFlow.cs:169:18:169:18 | access to local variable x | access to local variable x | -| ArrayFlow.cs:181:17:181:23 | object creation of type A : A | ArrayFlow.cs:181:17:181:23 | object creation of type A : A | ArrayFlow.cs:185:18:185:35 | access to property Current | $@ | ArrayFlow.cs:185:18:185:35 | access to property Current | access to property Current | diff --git a/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.cs b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs similarity index 100% rename from csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.cs rename to csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs diff --git a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected new file mode 100644 index 00000000000..d0019ee529e --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected @@ -0,0 +1,235 @@ +edges +| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:12:14:12:19 | access to array element | +| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:13:18:13:20 | access to local variable as : A[] | +| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:14:20:14:22 | access to local variable as : A[] | +| CollectionFlow.cs:13:18:13:20 | access to local variable as : A[] | CollectionFlow.cs:208:40:208:41 | ts : A[] | +| CollectionFlow.cs:14:20:14:22 | access to local variable as : A[] | CollectionFlow.cs:14:14:14:23 | call to method First | +| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:31:14:31:19 | access to array element | +| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:32:18:32:20 | access to local variable as : A[] | +| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:33:20:33:22 | access to local variable as : A[] | +| CollectionFlow.cs:32:18:32:20 | access to local variable as : A[] | CollectionFlow.cs:208:40:208:41 | ts : A[] | +| CollectionFlow.cs:33:20:33:22 | access to local variable as : A[] | CollectionFlow.cs:33:14:33:23 | call to method First | +| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:51:14:51:20 | access to indexer | +| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:52:22:52:25 | access to local variable list : List | +| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:53:24:53:27 | access to local variable list : List | +| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:51:14:51:20 | access to indexer | +| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:52:22:52:25 | access to local variable list : List | +| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:53:24:53:27 | access to local variable list : List | +| CollectionFlow.cs:52:22:52:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | +| CollectionFlow.cs:53:24:53:27 | access to local variable list : List | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | +| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:60:14:60:20 | access to indexer | +| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:61:22:61:25 | access to local variable list : List | +| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:62:24:62:27 | access to local variable list : List | +| CollectionFlow.cs:61:22:61:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | +| CollectionFlow.cs:62:24:62:27 | access to local variable list : List | CollectionFlow.cs:62:14:62:28 | call to method ListFirst | +| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:69:14:69:20 | access to indexer | +| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:70:22:70:25 | access to local variable list : List | +| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:71:24:71:27 | access to local variable list : List | +| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:69:14:69:20 | access to indexer | +| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:70:22:70:25 | access to local variable list : List | +| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:71:24:71:27 | access to local variable list : List | +| CollectionFlow.cs:70:22:70:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | +| CollectionFlow.cs:71:24:71:27 | access to local variable list : List | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | +| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:77:14:77:20 | access to indexer | +| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:78:22:78:25 | access to local variable list : List | +| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:79:24:79:27 | access to local variable list : List | +| CollectionFlow.cs:78:22:78:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | +| CollectionFlow.cs:79:24:79:27 | access to local variable list : List | CollectionFlow.cs:79:14:79:28 | call to method ListFirst | +| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:87:14:87:20 | access to indexer | +| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:88:22:88:25 | access to local variable list : List | +| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:89:24:89:27 | access to local variable list : List | +| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:87:14:87:20 | access to indexer | +| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:88:22:88:25 | access to local variable list : List | +| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:89:24:89:27 | access to local variable list : List | +| CollectionFlow.cs:88:22:88:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | +| CollectionFlow.cs:89:24:89:27 | access to local variable list : List | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | +| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:96:14:96:20 | access to indexer | +| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:97:22:97:25 | access to local variable list : List | +| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:98:24:98:27 | access to local variable list : List | +| CollectionFlow.cs:97:22:97:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | +| CollectionFlow.cs:98:24:98:27 | access to local variable list : List | CollectionFlow.cs:98:14:98:28 | call to method ListFirst | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:106:14:106:20 | access to indexer | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:14:106:20 | access to indexer | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | +| CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | +| CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:14:117:20 | access to indexer | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | +| CollectionFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | +| CollectionFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:128:14:128:20 | access to indexer | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:128:14:128:20 | access to indexer | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | +| CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | +| CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:138:14:138:20 | access to indexer | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | +| CollectionFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | +| CollectionFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | +| CollectionFlow.cs:166:17:166:23 | object creation of type A : A | CollectionFlow.cs:169:18:169:18 | access to local variable x | +| CollectionFlow.cs:181:17:181:23 | object creation of type A : A | CollectionFlow.cs:185:18:185:35 | access to property Current | +| CollectionFlow.cs:208:40:208:41 | ts : A[] | CollectionFlow.cs:208:52:208:56 | access to array element | +| CollectionFlow.cs:210:49:210:52 | list : List | CollectionFlow.cs:210:63:210:69 | access to indexer | +| CollectionFlow.cs:212:61:212:64 | dict : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | +nodes +| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:12:14:12:19 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:13:18:13:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:14:14:14:23 | call to method First | semmle.label | call to method First | +| CollectionFlow.cs:14:20:14:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:31:14:31:19 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:32:18:32:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:33:14:33:23 | call to method First | semmle.label | call to method First | +| CollectionFlow.cs:33:20:33:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:51:14:51:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:52:22:52:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:53:14:53:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:53:24:53:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:60:14:60:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:61:22:61:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:62:14:62:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:62:24:62:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:69:14:69:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:70:22:70:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:71:14:71:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:71:24:71:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:77:14:77:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:78:22:78:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:79:14:79:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:79:24:79:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:87:14:87:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:88:22:88:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:89:14:89:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:89:24:89:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:96:14:96:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:97:22:97:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:98:14:98:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:98:24:98:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:106:14:106:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:117:14:117:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| CollectionFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| CollectionFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:128:14:128:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:138:14:138:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | +| CollectionFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | +| CollectionFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:166:17:166:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:169:18:169:18 | access to local variable x | semmle.label | access to local variable x | +| CollectionFlow.cs:181:17:181:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:185:18:185:35 | access to property Current | semmle.label | access to property Current | +| CollectionFlow.cs:208:40:208:41 | ts : A[] | semmle.label | ts : A[] | +| CollectionFlow.cs:208:52:208:56 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:210:49:210:52 | list : List | semmle.label | list : List | +| CollectionFlow.cs:210:63:210:69 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:212:61:212:64 | dict : Dictionary | semmle.label | dict : Dictionary | +| CollectionFlow.cs:212:75:212:81 | access to indexer | semmle.label | access to indexer | +#select +| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:12:14:12:19 | access to array element | $@ | CollectionFlow.cs:12:14:12:19 | access to array element | access to array element | +| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:14:14:14:23 | call to method First | $@ | CollectionFlow.cs:14:14:14:23 | call to method First | call to method First | +| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:208:52:208:56 | access to array element | $@ | CollectionFlow.cs:208:52:208:56 | access to array element | access to array element | +| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:31:14:31:19 | access to array element | $@ | CollectionFlow.cs:31:14:31:19 | access to array element | access to array element | +| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:33:14:33:23 | call to method First | $@ | CollectionFlow.cs:33:14:33:23 | call to method First | call to method First | +| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:208:52:208:56 | access to array element | $@ | CollectionFlow.cs:208:52:208:56 | access to array element | access to array element | +| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:51:14:51:20 | access to indexer | $@ | CollectionFlow.cs:51:14:51:20 | access to indexer | access to indexer | +| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | $@ | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:51:14:51:20 | access to indexer | $@ | CollectionFlow.cs:51:14:51:20 | access to indexer | access to indexer | +| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | $@ | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:60:14:60:20 | access to indexer | $@ | CollectionFlow.cs:60:14:60:20 | access to indexer | access to indexer | +| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:62:14:62:28 | call to method ListFirst | $@ | CollectionFlow.cs:62:14:62:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:69:14:69:20 | access to indexer | $@ | CollectionFlow.cs:69:14:69:20 | access to indexer | access to indexer | +| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | $@ | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:69:14:69:20 | access to indexer | $@ | CollectionFlow.cs:69:14:69:20 | access to indexer | access to indexer | +| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | $@ | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:77:14:77:20 | access to indexer | $@ | CollectionFlow.cs:77:14:77:20 | access to indexer | access to indexer | +| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:79:14:79:28 | call to method ListFirst | $@ | CollectionFlow.cs:79:14:79:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:87:14:87:20 | access to indexer | $@ | CollectionFlow.cs:87:14:87:20 | access to indexer | access to indexer | +| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | $@ | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:87:14:87:20 | access to indexer | $@ | CollectionFlow.cs:87:14:87:20 | access to indexer | access to indexer | +| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | $@ | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:96:14:96:20 | access to indexer | $@ | CollectionFlow.cs:96:14:96:20 | access to indexer | access to indexer | +| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:98:14:98:28 | call to method ListFirst | $@ | CollectionFlow.cs:98:14:98:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:106:14:106:20 | access to indexer | $@ | CollectionFlow.cs:106:14:106:20 | access to indexer | access to indexer | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:14:106:20 | access to indexer | $@ | CollectionFlow.cs:106:14:106:20 | access to indexer | access to indexer | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:14:117:20 | access to indexer | $@ | CollectionFlow.cs:117:14:117:20 | access to indexer | access to indexer | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:128:14:128:20 | access to indexer | $@ | CollectionFlow.cs:128:14:128:20 | access to indexer | access to indexer | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:128:14:128:20 | access to indexer | $@ | CollectionFlow.cs:128:14:128:20 | access to indexer | access to indexer | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:138:14:138:20 | access to indexer | $@ | CollectionFlow.cs:138:14:138:20 | access to indexer | access to indexer | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | call to method DictFirstValueA | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | call to method DictFirstValueC | +| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | +| CollectionFlow.cs:166:17:166:23 | object creation of type A : A | CollectionFlow.cs:166:17:166:23 | object creation of type A : A | CollectionFlow.cs:169:18:169:18 | access to local variable x | $@ | CollectionFlow.cs:169:18:169:18 | access to local variable x | access to local variable x | +| CollectionFlow.cs:181:17:181:23 | object creation of type A : A | CollectionFlow.cs:181:17:181:23 | object creation of type A : A | CollectionFlow.cs:185:18:185:35 | access to property Current | $@ | CollectionFlow.cs:185:18:185:35 | access to property Current | access to property Current | diff --git a/csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.ql b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.ql similarity index 100% rename from csharp/ql/test/library-tests/dataflow/arrays/ArrayFlow.ql rename to csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.ql From e186c9ddd190a83f9bd5d1e8b8f355ca4e4cafda Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 20 Apr 2020 09:29:51 +0200 Subject: [PATCH 456/459] C#: Update data-flow collection test method names --- .../dataflow/collections/CollectionFlow.cs | 88 ++-- .../collections/CollectionFlow.expected | 464 +++++++++--------- 2 files changed, 277 insertions(+), 275 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs index 37ae6c6d299..3565ba0b6ea 100644 --- a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs @@ -3,9 +3,11 @@ using System; using System.Collections.Generic; using System.Linq; -public class A +public class CollectionFlow { - public void M1() + public class A { } + + public void ArrayInitializerFlow() { var a = new A(); var @as = new[] { a }; @@ -14,7 +16,7 @@ public class A Sink(First(@as)); // flow } - public void M2(A other) + public void ArrayInitializerNoFlow(A other) { var a = new A(); var @as = new[] { other }; @@ -23,7 +25,7 @@ public class A Sink(First(@as)); // no flow } - public void M3() + public void ArrayAssignmentFlow() { var a = new A(); var @as = new A[1]; @@ -33,7 +35,7 @@ public class A Sink(First(@as)); // flow } - public void M4(A other) + public void ArrayAssignmentNoFlow(A other) { var a = new A(); var @as = new A[1]; @@ -43,7 +45,7 @@ public class A Sink(First(@as)); // no flow } - public void M5() + public void ListAssignmentFlow() { var a = new A(); var list = new List(); @@ -53,7 +55,7 @@ public class A Sink(ListFirst(list)); // flow } - public void M6(A other) + public void ListAssignmentNoFlow(A other) { var list = new List(); list[0] = other; @@ -62,7 +64,7 @@ public class A Sink(ListFirst(list)); // no flow } - public void M7() + public void ListInitializerFlow() { var a = new A(); var list = new List() { a }; @@ -71,7 +73,7 @@ public class A Sink(ListFirst(list)); // flow } - public void M8(A other) + public void ListInitializerNoFlow(A other) { var list = new List() { other }; Sink(list[0]); // no flow @@ -79,7 +81,7 @@ public class A Sink(ListFirst(list)); // no flow } - public void M9() + public void ListAddFlow() { var a = new A(); var list = new List(); @@ -89,7 +91,7 @@ public class A Sink(ListFirst(list)); // flow } - public void M10(A other) + public void ListAddNoFlow(A other) { var list = new List(); list.Add(other); @@ -98,70 +100,70 @@ public class A Sink(ListFirst(list)); // no flow } - public void M11() + public void DictionaryAssignmentFlow() { var a = new A(); var dict = new Dictionary(); dict[0] = a; Sink(dict[0]); // flow SinkDictValue(dict); // flow - Sink(DictFirstValueA(dict)); // flow - Sink(DictFirstValueB(dict)); // flow [MISSING] - Sink(DictFirstValueC(dict)); // flow + Sink(DictIndexZero(dict)); // flow + Sink(DictFirstValue(dict)); // flow [MISSING] + Sink(DictValuesFirst(dict)); // flow } - public void M12(A other) + public void DictionaryAssignmentNoFlow(A other) { var dict = new Dictionary(); dict[0] = other; Sink(dict[0]); // no flow SinkDictValue(dict); // no flow - Sink(DictFirstValueA(dict)); // no flow - Sink(DictFirstValueB(dict)); // no flow - Sink(DictFirstValueC(dict)); // no flow + Sink(DictIndexZero(dict)); // no flow + Sink(DictFirstValue(dict)); // no flow + Sink(DictValuesFirst(dict)); // no flow } - public void M13() + public void DictionaryValueInitializerFlow() { var a = new A(); var dict = new Dictionary() { { 0, a } }; Sink(dict[0]); // flow SinkDictValue(dict); // flow - Sink(DictFirstValueA(dict)); // flow - Sink(DictFirstValueB(dict)); // flow [MISSING] - Sink(DictFirstValueC(dict)); // flow + Sink(DictIndexZero(dict)); // flow + Sink(DictFirstValue(dict)); // flow [MISSING] + Sink(DictValuesFirst(dict)); // flow } - public void M14(A other) + public void DictionaryValueInitializerNoFlow(A other) { var dict = new Dictionary() { { 0, other } }; Sink(dict[0]); // no flow SinkDictValue(dict); // no flow - Sink(DictFirstValueA(dict)); // no flow - Sink(DictFirstValueB(dict)); // no flow - Sink(DictFirstValueC(dict)); // no flow + Sink(DictIndexZero(dict)); // no flow + Sink(DictFirstValue(dict)); // no flow + Sink(DictValuesFirst(dict)); // no flow } - public void M15() + public void DictionaryKeyInitializerFlow() { var a = new A(); var dict = new Dictionary() { { a, 0 } }; Sink(dict.Keys.First()); // flow [MISSING] SinkDictKey(dict); // flow [MISSING] - Sink(DictFirstKeyA(dict)); // flow [MISSING] - Sink(DictFirstKeyB(dict)); // flow [MISSING] + Sink(DictKeysFirst(dict)); // flow [MISSING] + Sink(DictFirstKey(dict)); // flow [MISSING] } - public void M16(A other) + public void DictionaryKeyInitializerNoFlow(A other) { var dict = new Dictionary() { { other, 0 } }; Sink(dict.Keys.First()); // no flow SinkDictKey(dict); // no flow - Sink(DictFirstKeyA(dict)); // no flow - Sink(DictFirstKeyB(dict)); // no flow + Sink(DictKeysFirst(dict)); // no flow + Sink(DictFirstKey(dict)); // no flow } - public void M17() + public void ForeachFlow() { var a = new A(); var @as = new[] { a }; @@ -169,14 +171,14 @@ public class A Sink(x); // flow } - public void M18(A other) + public void ForeachNoFlow(A other) { var @as = new[] { other }; foreach (var x in @as) Sink(x); // no flow } - public void M19() + public void ArrayGetEnumeratorFlow() { var a = new A(); var @as = new[] { a }; @@ -185,7 +187,7 @@ public class A Sink(enumerator.Current); // flow } - public void M20(A other) + public void ArrayGetEnumeratorNoFlow(A other) { var @as = new[] { other }; var enumerator = @as.GetEnumerator(); @@ -193,7 +195,7 @@ public class A Sink(enumerator.Current); // no flow } - public void M21() + public void ListGetEnumeratorFlow() { var a = new A(); var list = new List(); @@ -217,13 +219,13 @@ public class A public static T ListFirst(IList list) => list[0]; - public static T DictFirstValueA(IDictionary dict) => dict[0]; + public static T DictIndexZero(IDictionary dict) => dict[0]; - public static T DictFirstValueB(IDictionary dict) => dict.First().Value; + public static T DictFirstValue(IDictionary dict) => dict.First().Value; - public static T DictFirstValueC(IDictionary dict) => dict.Values.First(); + public static T DictValuesFirst(IDictionary dict) => dict.Values.First(); - public static T DictFirstKeyA(IDictionary dict) => dict.Keys.First(); + public static T DictKeysFirst(IDictionary dict) => dict.Keys.First(); - public static T DictFirstKeyB(IDictionary dict) => dict.First().Key; + public static T DictFirstKey(IDictionary dict) => dict.First().Key; } diff --git a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected index d0019ee529e..c6cc298ea94 100644 --- a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected @@ -1,235 +1,235 @@ edges -| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:12:14:12:19 | access to array element | -| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:13:18:13:20 | access to local variable as : A[] | -| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:14:20:14:22 | access to local variable as : A[] | -| CollectionFlow.cs:13:18:13:20 | access to local variable as : A[] | CollectionFlow.cs:208:40:208:41 | ts : A[] | -| CollectionFlow.cs:14:20:14:22 | access to local variable as : A[] | CollectionFlow.cs:14:14:14:23 | call to method First | -| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:31:14:31:19 | access to array element | -| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:32:18:32:20 | access to local variable as : A[] | -| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:33:20:33:22 | access to local variable as : A[] | -| CollectionFlow.cs:32:18:32:20 | access to local variable as : A[] | CollectionFlow.cs:208:40:208:41 | ts : A[] | -| CollectionFlow.cs:33:20:33:22 | access to local variable as : A[] | CollectionFlow.cs:33:14:33:23 | call to method First | -| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:51:14:51:20 | access to indexer | -| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:52:22:52:25 | access to local variable list : List | -| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:53:24:53:27 | access to local variable list : List | -| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:51:14:51:20 | access to indexer | -| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:52:22:52:25 | access to local variable list : List | -| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:53:24:53:27 | access to local variable list : List | -| CollectionFlow.cs:52:22:52:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | -| CollectionFlow.cs:53:24:53:27 | access to local variable list : List | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | -| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:60:14:60:20 | access to indexer | -| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:61:22:61:25 | access to local variable list : List | -| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:62:24:62:27 | access to local variable list : List | -| CollectionFlow.cs:61:22:61:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | -| CollectionFlow.cs:62:24:62:27 | access to local variable list : List | CollectionFlow.cs:62:14:62:28 | call to method ListFirst | -| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:69:14:69:20 | access to indexer | -| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:70:22:70:25 | access to local variable list : List | -| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:71:24:71:27 | access to local variable list : List | -| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:69:14:69:20 | access to indexer | -| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:70:22:70:25 | access to local variable list : List | -| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:71:24:71:27 | access to local variable list : List | -| CollectionFlow.cs:70:22:70:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | -| CollectionFlow.cs:71:24:71:27 | access to local variable list : List | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | -| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:77:14:77:20 | access to indexer | -| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:78:22:78:25 | access to local variable list : List | -| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:79:24:79:27 | access to local variable list : List | -| CollectionFlow.cs:78:22:78:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | -| CollectionFlow.cs:79:24:79:27 | access to local variable list : List | CollectionFlow.cs:79:14:79:28 | call to method ListFirst | -| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:87:14:87:20 | access to indexer | -| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:88:22:88:25 | access to local variable list : List | -| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:89:24:89:27 | access to local variable list : List | -| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:87:14:87:20 | access to indexer | -| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:88:22:88:25 | access to local variable list : List | -| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:89:24:89:27 | access to local variable list : List | -| CollectionFlow.cs:88:22:88:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | -| CollectionFlow.cs:89:24:89:27 | access to local variable list : List | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | -| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:96:14:96:20 | access to indexer | -| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:97:22:97:25 | access to local variable list : List | -| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:98:24:98:27 | access to local variable list : List | -| CollectionFlow.cs:97:22:97:25 | access to local variable list : List | CollectionFlow.cs:210:49:210:52 | list : List | -| CollectionFlow.cs:98:24:98:27 | access to local variable list : List | CollectionFlow.cs:98:14:98:28 | call to method ListFirst | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:106:14:106:20 | access to indexer | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:14:106:20 | access to indexer | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | -| CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | -| CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:14:117:20 | access to indexer | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | -| CollectionFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | -| CollectionFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:128:14:128:20 | access to indexer | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:128:14:128:20 | access to indexer | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | -| CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | -| CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:138:14:138:20 | access to indexer | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | -| CollectionFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | CollectionFlow.cs:212:61:212:64 | dict : Dictionary | -| CollectionFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | -| CollectionFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | -| CollectionFlow.cs:166:17:166:23 | object creation of type A : A | CollectionFlow.cs:169:18:169:18 | access to local variable x | -| CollectionFlow.cs:181:17:181:23 | object creation of type A : A | CollectionFlow.cs:185:18:185:35 | access to property Current | -| CollectionFlow.cs:208:40:208:41 | ts : A[] | CollectionFlow.cs:208:52:208:56 | access to array element | -| CollectionFlow.cs:210:49:210:52 | list : List | CollectionFlow.cs:210:63:210:69 | access to indexer | -| CollectionFlow.cs:212:61:212:64 | dict : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:14:14:14:19 | access to array element | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:15:18:15:20 | access to local variable as : A[] | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:16:20:16:22 | access to local variable as : A[] | +| CollectionFlow.cs:15:18:15:20 | access to local variable as : A[] | CollectionFlow.cs:210:40:210:41 | ts : A[] | +| CollectionFlow.cs:16:20:16:22 | access to local variable as : A[] | CollectionFlow.cs:16:14:16:23 | call to method First | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:33:14:33:19 | access to array element | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:34:18:34:20 | access to local variable as : A[] | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:35:20:35:22 | access to local variable as : A[] | +| CollectionFlow.cs:34:18:34:20 | access to local variable as : A[] | CollectionFlow.cs:210:40:210:41 | ts : A[] | +| CollectionFlow.cs:35:20:35:22 | access to local variable as : A[] | CollectionFlow.cs:35:14:35:23 | call to method First | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:53:14:53:20 | access to indexer | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:54:22:54:25 | access to local variable list : List | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:55:24:55:27 | access to local variable list : List | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:53:14:53:20 | access to indexer | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:54:22:54:25 | access to local variable list : List | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:55:24:55:27 | access to local variable list : List | +| CollectionFlow.cs:54:22:54:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:55:24:55:27 | access to local variable list : List | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:62:14:62:20 | access to indexer | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:63:22:63:25 | access to local variable list : List | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:64:24:64:27 | access to local variable list : List | +| CollectionFlow.cs:63:22:63:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:64:24:64:27 | access to local variable list : List | CollectionFlow.cs:64:14:64:28 | call to method ListFirst | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:71:14:71:20 | access to indexer | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:72:22:72:25 | access to local variable list : List | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:73:24:73:27 | access to local variable list : List | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:71:14:71:20 | access to indexer | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:72:22:72:25 | access to local variable list : List | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:73:24:73:27 | access to local variable list : List | +| CollectionFlow.cs:72:22:72:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:73:24:73:27 | access to local variable list : List | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:79:14:79:20 | access to indexer | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:80:22:80:25 | access to local variable list : List | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:81:24:81:27 | access to local variable list : List | +| CollectionFlow.cs:80:22:80:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:81:24:81:27 | access to local variable list : List | CollectionFlow.cs:81:14:81:28 | call to method ListFirst | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:89:14:89:20 | access to indexer | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:90:22:90:25 | access to local variable list : List | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:91:24:91:27 | access to local variable list : List | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:89:14:89:20 | access to indexer | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:90:22:90:25 | access to local variable list : List | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:91:24:91:27 | access to local variable list : List | +| CollectionFlow.cs:90:22:90:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:91:24:91:27 | access to local variable list : List | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:98:14:98:20 | access to indexer | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:99:22:99:25 | access to local variable list : List | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:100:24:100:27 | access to local variable list : List | +| CollectionFlow.cs:99:22:99:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:100:24:100:27 | access to local variable list : List | CollectionFlow.cs:100:14:100:28 | call to method ListFirst | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:108:14:108:20 | access to indexer | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:14:108:20 | access to indexer | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | +| CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:14:119:20 | access to indexer | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:120:23:120:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:28:121:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:123:30:123:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:120:23:120:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:121:28:121:31 | access to local variable dict : Dictionary | CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | +| CollectionFlow.cs:123:30:123:33 | access to local variable dict : Dictionary | CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:130:14:130:20 | access to indexer | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:14:130:20 | access to indexer | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | +| CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:14:140:20 | access to indexer | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:141:23:141:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:28:142:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:144:30:144:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:141:23:141:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:142:28:142:31 | access to local variable dict : Dictionary | CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | +| CollectionFlow.cs:144:30:144:33 | access to local variable dict : Dictionary | CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | +| CollectionFlow.cs:168:17:168:23 | object creation of type A : A | CollectionFlow.cs:171:18:171:18 | access to local variable x | +| CollectionFlow.cs:183:17:183:23 | object creation of type A : A | CollectionFlow.cs:187:18:187:35 | access to property Current | +| CollectionFlow.cs:210:40:210:41 | ts : A[] | CollectionFlow.cs:210:52:210:56 | access to array element | +| CollectionFlow.cs:212:49:212:52 | list : List | CollectionFlow.cs:212:63:212:69 | access to indexer | +| CollectionFlow.cs:214:61:214:64 | dict : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | nodes -| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:12:14:12:19 | access to array element | semmle.label | access to array element | -| CollectionFlow.cs:13:18:13:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| CollectionFlow.cs:14:14:14:23 | call to method First | semmle.label | call to method First | -| CollectionFlow.cs:14:20:14:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:31:14:31:19 | access to array element | semmle.label | access to array element | -| CollectionFlow.cs:32:18:32:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| CollectionFlow.cs:33:14:33:23 | call to method First | semmle.label | call to method First | -| CollectionFlow.cs:33:20:33:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | -| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| CollectionFlow.cs:51:14:51:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:52:22:52:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:53:14:53:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| CollectionFlow.cs:53:24:53:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| CollectionFlow.cs:60:14:60:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:61:22:61:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:62:14:62:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| CollectionFlow.cs:62:24:62:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | semmle.label | object creation of type List : List | -| CollectionFlow.cs:69:14:69:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:70:22:70:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:71:14:71:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| CollectionFlow.cs:71:24:71:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | semmle.label | object creation of type List : List | -| CollectionFlow.cs:77:14:77:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:78:22:78:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:79:14:79:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| CollectionFlow.cs:79:24:79:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| CollectionFlow.cs:87:14:87:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:88:22:88:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:89:14:89:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| CollectionFlow.cs:89:24:89:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | semmle.label | object creation of type List : List | -| CollectionFlow.cs:96:14:96:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:97:22:97:25 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:98:14:98:28 | call to method ListFirst | semmle.label | call to method ListFirst | -| CollectionFlow.cs:98:24:98:27 | access to local variable list : List | semmle.label | access to local variable list : List | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| CollectionFlow.cs:106:14:106:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:107:23:107:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| CollectionFlow.cs:108:30:108:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| CollectionFlow.cs:110:30:110:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| CollectionFlow.cs:117:14:117:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:118:23:118:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| CollectionFlow.cs:119:30:119:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| CollectionFlow.cs:121:30:121:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| CollectionFlow.cs:128:14:128:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:129:23:129:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| CollectionFlow.cs:130:30:130:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| CollectionFlow.cs:132:30:132:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | -| CollectionFlow.cs:138:14:138:20 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:139:23:139:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | semmle.label | call to method DictFirstValueA | -| CollectionFlow.cs:140:30:140:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | semmle.label | call to method DictFirstValueC | -| CollectionFlow.cs:142:30:142:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | -| CollectionFlow.cs:166:17:166:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:169:18:169:18 | access to local variable x | semmle.label | access to local variable x | -| CollectionFlow.cs:181:17:181:23 | object creation of type A : A | semmle.label | object creation of type A : A | -| CollectionFlow.cs:185:18:185:35 | access to property Current | semmle.label | access to property Current | -| CollectionFlow.cs:208:40:208:41 | ts : A[] | semmle.label | ts : A[] | -| CollectionFlow.cs:208:52:208:56 | access to array element | semmle.label | access to array element | -| CollectionFlow.cs:210:49:210:52 | list : List | semmle.label | list : List | -| CollectionFlow.cs:210:63:210:69 | access to indexer | semmle.label | access to indexer | -| CollectionFlow.cs:212:61:212:64 | dict : Dictionary | semmle.label | dict : Dictionary | -| CollectionFlow.cs:212:75:212:81 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:14:14:14:19 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:15:18:15:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:16:14:16:23 | call to method First | semmle.label | call to method First | +| CollectionFlow.cs:16:20:16:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:33:14:33:19 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:34:18:34:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:35:14:35:23 | call to method First | semmle.label | call to method First | +| CollectionFlow.cs:35:20:35:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:53:14:53:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:54:22:54:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:55:14:55:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:55:24:55:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:62:14:62:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:63:22:63:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:64:14:64:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:64:24:64:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:71:14:71:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:72:22:72:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:73:14:73:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:73:24:73:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:79:14:79:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:80:22:80:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:81:14:81:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:81:24:81:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:89:14:89:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:90:22:90:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:91:14:91:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:91:24:91:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:98:14:98:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:99:22:99:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:100:14:100:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:100:24:100:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:108:14:108:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:119:14:119:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:120:23:120:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:121:28:121:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:123:30:123:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:130:14:130:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:140:14:140:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:141:23:141:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:142:28:142:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:144:30:144:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:168:17:168:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:171:18:171:18 | access to local variable x | semmle.label | access to local variable x | +| CollectionFlow.cs:183:17:183:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:187:18:187:35 | access to property Current | semmle.label | access to property Current | +| CollectionFlow.cs:210:40:210:41 | ts : A[] | semmle.label | ts : A[] | +| CollectionFlow.cs:210:52:210:56 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:212:49:212:52 | list : List | semmle.label | list : List | +| CollectionFlow.cs:212:63:212:69 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:214:61:214:64 | dict : Dictionary | semmle.label | dict : Dictionary | +| CollectionFlow.cs:214:75:214:81 | access to indexer | semmle.label | access to indexer | #select -| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:12:14:12:19 | access to array element | $@ | CollectionFlow.cs:12:14:12:19 | access to array element | access to array element | -| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:14:14:14:23 | call to method First | $@ | CollectionFlow.cs:14:14:14:23 | call to method First | call to method First | -| CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:10:17:10:23 | object creation of type A : A | CollectionFlow.cs:208:52:208:56 | access to array element | $@ | CollectionFlow.cs:208:52:208:56 | access to array element | access to array element | -| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:31:14:31:19 | access to array element | $@ | CollectionFlow.cs:31:14:31:19 | access to array element | access to array element | -| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:33:14:33:23 | call to method First | $@ | CollectionFlow.cs:33:14:33:23 | call to method First | call to method First | -| CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:28:17:28:23 | object creation of type A : A | CollectionFlow.cs:208:52:208:56 | access to array element | $@ | CollectionFlow.cs:208:52:208:56 | access to array element | access to array element | -| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:51:14:51:20 | access to indexer | $@ | CollectionFlow.cs:51:14:51:20 | access to indexer | access to indexer | -| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | $@ | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:48:17:48:23 | object creation of type A : A | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:51:14:51:20 | access to indexer | $@ | CollectionFlow.cs:51:14:51:20 | access to indexer | access to indexer | -| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | $@ | CollectionFlow.cs:53:14:53:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:49:20:49:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:60:14:60:20 | access to indexer | $@ | CollectionFlow.cs:60:14:60:20 | access to indexer | access to indexer | -| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:62:14:62:28 | call to method ListFirst | $@ | CollectionFlow.cs:62:14:62:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:58:20:58:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:69:14:69:20 | access to indexer | $@ | CollectionFlow.cs:69:14:69:20 | access to indexer | access to indexer | -| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | $@ | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:67:17:67:23 | object creation of type A : A | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:69:14:69:20 | access to indexer | $@ | CollectionFlow.cs:69:14:69:20 | access to indexer | access to indexer | -| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | $@ | CollectionFlow.cs:71:14:71:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:68:20:68:38 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:77:14:77:20 | access to indexer | $@ | CollectionFlow.cs:77:14:77:20 | access to indexer | access to indexer | -| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:79:14:79:28 | call to method ListFirst | $@ | CollectionFlow.cs:79:14:79:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:76:20:76:42 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:87:14:87:20 | access to indexer | $@ | CollectionFlow.cs:87:14:87:20 | access to indexer | access to indexer | -| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | $@ | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:84:17:84:23 | object creation of type A : A | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:87:14:87:20 | access to indexer | $@ | CollectionFlow.cs:87:14:87:20 | access to indexer | access to indexer | -| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | $@ | CollectionFlow.cs:89:14:89:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:85:20:85:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:96:14:96:20 | access to indexer | $@ | CollectionFlow.cs:96:14:96:20 | access to indexer | access to indexer | -| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:98:14:98:28 | call to method ListFirst | $@ | CollectionFlow.cs:98:14:98:28 | call to method ListFirst | call to method ListFirst | -| CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:94:20:94:32 | object creation of type List : List | CollectionFlow.cs:210:63:210:69 | access to indexer | $@ | CollectionFlow.cs:210:63:210:69 | access to indexer | access to indexer | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:106:14:106:20 | access to indexer | $@ | CollectionFlow.cs:106:14:106:20 | access to indexer | access to indexer | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:103:17:103:23 | object creation of type A : A | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:14:106:20 | access to indexer | $@ | CollectionFlow.cs:106:14:106:20 | access to indexer | access to indexer | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:108:14:108:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:110:14:110:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:104:20:104:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:14:117:20 | access to indexer | $@ | CollectionFlow.cs:117:14:117:20 | access to indexer | access to indexer | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:119:14:119:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:121:14:121:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:115:20:115:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:128:14:128:20 | access to indexer | $@ | CollectionFlow.cs:128:14:128:20 | access to indexer | access to indexer | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:126:17:126:23 | object creation of type A : A | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:128:14:128:20 | access to indexer | $@ | CollectionFlow.cs:128:14:128:20 | access to indexer | access to indexer | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:130:14:130:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:132:14:132:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:127:20:127:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:138:14:138:20 | access to indexer | $@ | CollectionFlow.cs:138:14:138:20 | access to indexer | access to indexer | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | $@ | CollectionFlow.cs:140:14:140:34 | call to method DictFirstValueA | call to method DictFirstValueA | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | $@ | CollectionFlow.cs:142:14:142:34 | call to method DictFirstValueC | call to method DictFirstValueC | -| CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:137:20:137:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:212:75:212:81 | access to indexer | $@ | CollectionFlow.cs:212:75:212:81 | access to indexer | access to indexer | -| CollectionFlow.cs:166:17:166:23 | object creation of type A : A | CollectionFlow.cs:166:17:166:23 | object creation of type A : A | CollectionFlow.cs:169:18:169:18 | access to local variable x | $@ | CollectionFlow.cs:169:18:169:18 | access to local variable x | access to local variable x | -| CollectionFlow.cs:181:17:181:23 | object creation of type A : A | CollectionFlow.cs:181:17:181:23 | object creation of type A : A | CollectionFlow.cs:185:18:185:35 | access to property Current | $@ | CollectionFlow.cs:185:18:185:35 | access to property Current | access to property Current | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:14:14:14:19 | access to array element | $@ | CollectionFlow.cs:14:14:14:19 | access to array element | access to array element | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:16:14:16:23 | call to method First | $@ | CollectionFlow.cs:16:14:16:23 | call to method First | call to method First | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:210:52:210:56 | access to array element | $@ | CollectionFlow.cs:210:52:210:56 | access to array element | access to array element | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:33:14:33:19 | access to array element | $@ | CollectionFlow.cs:33:14:33:19 | access to array element | access to array element | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:35:14:35:23 | call to method First | $@ | CollectionFlow.cs:35:14:35:23 | call to method First | call to method First | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:210:52:210:56 | access to array element | $@ | CollectionFlow.cs:210:52:210:56 | access to array element | access to array element | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:53:14:53:20 | access to indexer | $@ | CollectionFlow.cs:53:14:53:20 | access to indexer | access to indexer | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | $@ | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:53:14:53:20 | access to indexer | $@ | CollectionFlow.cs:53:14:53:20 | access to indexer | access to indexer | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | $@ | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:62:14:62:20 | access to indexer | $@ | CollectionFlow.cs:62:14:62:20 | access to indexer | access to indexer | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:64:14:64:28 | call to method ListFirst | $@ | CollectionFlow.cs:64:14:64:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:71:14:71:20 | access to indexer | $@ | CollectionFlow.cs:71:14:71:20 | access to indexer | access to indexer | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | $@ | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:71:14:71:20 | access to indexer | $@ | CollectionFlow.cs:71:14:71:20 | access to indexer | access to indexer | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | $@ | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:79:14:79:20 | access to indexer | $@ | CollectionFlow.cs:79:14:79:20 | access to indexer | access to indexer | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:81:14:81:28 | call to method ListFirst | $@ | CollectionFlow.cs:81:14:81:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:89:14:89:20 | access to indexer | $@ | CollectionFlow.cs:89:14:89:20 | access to indexer | access to indexer | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | $@ | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:89:14:89:20 | access to indexer | $@ | CollectionFlow.cs:89:14:89:20 | access to indexer | access to indexer | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | $@ | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:98:14:98:20 | access to indexer | $@ | CollectionFlow.cs:98:14:98:20 | access to indexer | access to indexer | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:100:14:100:28 | call to method ListFirst | $@ | CollectionFlow.cs:100:14:100:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:108:14:108:20 | access to indexer | $@ | CollectionFlow.cs:108:14:108:20 | access to indexer | access to indexer | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:14:108:20 | access to indexer | $@ | CollectionFlow.cs:108:14:108:20 | access to indexer | access to indexer | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:14:119:20 | access to indexer | $@ | CollectionFlow.cs:119:14:119:20 | access to indexer | access to indexer | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:130:14:130:20 | access to indexer | $@ | CollectionFlow.cs:130:14:130:20 | access to indexer | access to indexer | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:14:130:20 | access to indexer | $@ | CollectionFlow.cs:130:14:130:20 | access to indexer | access to indexer | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:14:140:20 | access to indexer | $@ | CollectionFlow.cs:140:14:140:20 | access to indexer | access to indexer | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:168:17:168:23 | object creation of type A : A | CollectionFlow.cs:168:17:168:23 | object creation of type A : A | CollectionFlow.cs:171:18:171:18 | access to local variable x | $@ | CollectionFlow.cs:171:18:171:18 | access to local variable x | access to local variable x | +| CollectionFlow.cs:183:17:183:23 | object creation of type A : A | CollectionFlow.cs:183:17:183:23 | object creation of type A : A | CollectionFlow.cs:187:18:187:35 | access to property Current | $@ | CollectionFlow.cs:187:18:187:35 | access to property Current | access to property Current | From c713ba7bfec53276bc18f34f74212fbd60808149 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 20 Apr 2020 10:51:42 +0200 Subject: [PATCH 457/459] fix typo --- javascript/ql/src/Expressions/MisspelledVariableName.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Expressions/MisspelledVariableName.ql b/javascript/ql/src/Expressions/MisspelledVariableName.ql index 9eeeb288134..b6f0ad88e3e 100644 --- a/javascript/ql/src/Expressions/MisspelledVariableName.ql +++ b/javascript/ql/src/Expressions/MisspelledVariableName.ql @@ -29,7 +29,7 @@ bindingset[name] int globalAccesses(string name) { result = count(GlobalVarAccess acc | acc.getName() = name) } /** - * Holds if our heuristic says that the local variable `lvd` seems to be a misspelling of the global variable `gvd`. + * Holds if our heuristic says that the local variable `lvd` seems to be a misspelling of the global variable `gva`. * Otherwise the global variable is likely the misspelling. */ predicate globalIsLikelyCorrect(GlobalVarAccess gva, VarDecl lvd) { From ead916702a7f71b8e3d33c2361bd06b0077d8d66 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Mon, 20 Apr 2020 09:32:35 +0100 Subject: [PATCH 458/459] C#: Take nullability into account when creating symbol entities. Otherwise, an entity with the wrong (cached) nullability could be created. --- .../Entities/Accessor.cs | 2 +- .../Entities/Constructor.cs | 2 +- .../Entities/Conversion.cs | 2 +- .../Entities/Destructor.cs | 2 +- .../Entities/Event.cs | 2 +- .../Entities/EventAccessor.cs | 2 +- .../Entities/Field.cs | 2 +- .../Entities/Indexer.cs | 2 +- .../Entities/LocalFunction.cs | 2 +- .../Entities/LocalVariable.cs | 2 +- .../Entities/OrdinaryMethod.cs | 2 +- .../Entities/Property.cs | 2 +- .../Entities/Types/ArrayType.cs | 2 +- .../Entities/Types/DynamicType.cs | 2 +- .../Entities/Types/NamedType.cs | 2 +- .../Entities/Types/PointerType.cs | 2 +- .../Entities/Types/TupleType.cs | 2 +- .../Entities/Types/Type.cs | 8 +++++ .../Entities/Types/TypeParameter.cs | 2 +- .../Entities/UserOperator.cs | 2 +- csharp/extractor/Semmle.Extraction/Context.cs | 33 ++++++++++++++++--- csharp/extractor/Semmle.Extraction/Entity.cs | 13 ++++++++ .../csharp8/NullableRefTypes.expected | 2 +- 23 files changed, 70 insertions(+), 24 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs index 98c021c8a6d..cc713b5ad2f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs @@ -77,7 +77,7 @@ namespace Semmle.Extraction.CSharp.Entities } public new static Accessor Create(Context cx, IMethodSymbol symbol) => - AccessorFactory.Instance.CreateEntity(cx, symbol); + AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class AccessorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs index 298f838cfb9..a9baacbf728 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs @@ -104,7 +104,7 @@ namespace Semmle.Extraction.CSharp.Entities { case MethodKind.StaticConstructor: case MethodKind.Constructor: - return ConstructorFactory.Instance.CreateEntity(cx, constructor); + return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor); default: throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs index e365ca53ae0..98758fb773f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs @@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities : base(cx, init) { } public new static Conversion Create(Context cx, IMethodSymbol symbol) => - ConversionFactory.Instance.CreateEntity(cx, symbol); + ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol); public override Microsoft.CodeAnalysis.Location ReportingLocation { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs index 33f3a330f94..65557b16b67 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs @@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities } public new static Destructor Create(Context cx, IMethodSymbol symbol) => - DestructorFactory.Instance.CreateEntity(cx, symbol); + DestructorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class DestructorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs index 224c81b9524..59f937a6331 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs @@ -60,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities TypeMention.Create(Context, syntaxType, this, type); } - public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntity(cx, symbol); + public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol); class EventFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs index 7dc0a4dfcff..da858b689dc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs @@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities } public new static EventAccessor Create(Context cx, IMethodSymbol symbol) => - EventAccessorFactory.Instance.CreateEntity(cx, symbol); + EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class EventAccessorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs index 7ae4572cd7d..f126b7ff52f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs @@ -18,7 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities type = new Lazy(() => Entities.Type.Create(cx, symbol.GetAnnotatedType())); } - public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntity(cx, field); + public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntityFromSymbol(cx, field); // Do not populate backing fields. // Populate Tuple fields. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs index b9ece3d8c8e..af07c41dd6b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs @@ -71,7 +71,7 @@ namespace Semmle.Extraction.CSharp.Entities TypeMention.Create(Context, syntax.Type, this, type); } - public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntity(cx, prop); + public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop); public override void WriteId(TextWriter trapFile) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs index e570802ab3d..8b90f6905dd 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs @@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.Write('*'); } - public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field); + public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntityFromSymbol(cx, field); class LocalFunctionFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs index 6d0f14a014e..02d89d08a2f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs @@ -43,7 +43,7 @@ namespace Semmle.Extraction.CSharp.Entities public static LocalVariable Create(Context cx, ISymbol local) { - return LocalVariableFactory.Instance.CreateEntity(cx, local); + return LocalVariableFactory.Instance.CreateEntityFromSymbol(cx, local); } void DefineConstantValue(TextWriter trapFile) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs index cb12918e72e..74e7de35a16 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs @@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp.Entities ExtractCompilerGenerated(trapFile); } - public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntity(cx, method); + public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method); class OrdinaryMethodFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs index e5e2cc8ab26..05ff97db805 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs @@ -113,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities { bool isIndexer = prop.IsIndexer || prop.Parameters.Any(); - return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntity(cx, prop); + return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop); } public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs index c4a79a7764b..9e211660344 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs @@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.Write(";type"); } - public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntity(cx, symbol); + public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); class ArrayTypeFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs index f5b6bf36c44..bfaba1cff85 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs @@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities DynamicType(Context cx, IDynamicTypeSymbol init) : base(cx, init) { } - public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntity(cx, type); + public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntityFromSymbol(cx, type); public override Microsoft.CodeAnalysis.Location ReportingLocation => Context.Compilation.ObjectType.Locations.FirstOrDefault(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 25145520aee..20b7bf12ca8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities typeArgumentsLazy = new Lazy(() => symbol.TypeArguments.Select(t => Create(cx, t)).ToArray()); } - public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntity(cx, type); + public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntityFromSymbol(cx, type); public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Error; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs index db8b5ff8c23..229666e6260 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs @@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities public Type PointedAtType { get; private set; } - public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntity(cx, symbol); + public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); class PointerTypeFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index b7e38fd88f4..ae9d3139a5c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities ///